Membuat kekacauan 1k intro untuk ZX-Spectrum


Awalnya, saya tidak berencana untuk melakukan demo di Chaos Constrictions 2018 , tetapi 2-3 minggu sebelum cc saya menyadari bahwa Anda tidak dapat pergi ke pesta demo dengan tangan kosong, dan memutuskan untuk menulis demo singkat untuk 386 / EGA / DOS .

Setelah dikompilasi dalam Turbo-C di bawah DOS my lib AnotherGraphicsLibrary , yang idealnya masuk dalam struktur beat plan dari mode EGA , saya kecewa dengan rem, terutama rem EGA . Demo dalam bentuk di mana saya ingin melihatnya, untuk periode yang sangat terbatas ini, tidak mungkin dilakukan.

Namun, saya tidak bisa menyerah dan tidak melakukan apa-apa. Dan kemudian saya ingat bahwa saya sudah lama ingin mengambil bagian dalam kontes demo ZX-Spectrum . Dan karena saya mendapatkan dua real 48k di tahun lalu, saya bisa mendapatkan kesenangan dari membuat demo. Ngomong-ngomong - bagi saya, hal yang paling penting dalam menulis demo adalah pengujian dalam kehidupan nyata, pengemulsi tidak memberikan kesenangan seperti itu dari proses, itu perasaan yang sangat indah ketika, setelah perubahan kode selanjutnya, Anda mengunggah demo ke kehidupan nyata, dan Anda melihat bagaimana perangkat keras yang sebenarnya mengocok byte dalam efek menggambar memori.

Karena saya hanya memiliki 48k real, saya memutuskan untuk membuat demo untuk 48k . Dan karena waktu yang terbatas dan kurangnya perkembangan, pilihan jatuh pada penciptaan int 1k (demo hanya 1 kilobyte, atau 1024 byte).

Terakhir kali saya mencolek as80 z80 di EmuZWin - emulator hebat dengan assembler bawaan . Namun sayangnya EmuZWin tidak bekerja pada sesuatu yang lebih tinggi dari Windows XP , atau buggy.
Setelah memeriksa berbagai pilihan, saya berhenti di sekelompok program Unreal + sjAsm + Notepad ++ , yang, menurut pendapat saya, jauh lebih mudah daripada EmuZWin dalam hal kenyamanan, tetapi, sebaliknya, hidup.

Saat menulis intro ini, saya melakukan, tepat di sumbernya, log pengembangan, berdasarkan yang mana teks berikut ini ditulis:

Halo Dunia!

Apa yang harus saya tulis pertama, memiliki hampir nol pengalaman dalam asm z80 ? Itu benar, output dari sprite 5x5 familiar atau 40x40 piksel, untuk salah satu efek (ironisnya, di masa depan, agar sesuai dengan 1k bagian yang belum selesai ini dibuang dari intro).

Hebatnya, itu sangat mudah untuk melakukan ini dari awal menggunakan label alamat jalur yang dibuat sebelumnya menggunakan Down HL .

Oh, register indeks, betapa mudahnya mereka, tetapi yang lebih lambat, mengkonsumsi bar secara harfiah. Saya harus membuang penggunaan mereka dari banyak tempat.

Masih di sini, di awal, saya menemukan gangguan sjAsm yang luar biasa, atau lebih tepatnya versi terbarunya. Disrealisme di Unreal menunjukkan urutan perintah yang benar-benar gila. Saya mengunduh versi kedua dari belakang - itu sudah mungkin untuk hidup dengannya entah bagaimana.



Jelas bahwa Anda tidak dapat menempatkan jumlah yang cukup dari sprite yang ditarik sebelumnya ke dalam 1k, jadi saya memutuskan untuk membuatnya secara dinamis. Dan tidak bagaimana pun, tetapi menggambar menggunakan poligon.

Oleh karena itu, prosedur kedua yang saya tulis adalah prosedur menggambar segitiga. Sebagian besar, itu adalah porting dari kode mereka sendiri yang ditulis dalam C. Dengan satu-satunya perbedaan global dari versi C , scanlines poligon dihasilkan terlebih dahulu, dan hanya kemudian mereka ditarik pada scanlines ini.

Setelah bahasa tingkat tinggi, Anda mendapatkan kesenangan dari jr alias 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: 

Saya sedikit terkejut dengan fakta bahwa ternyata pada waktu yang masuk akal untuk menulis draw_triangle yang berfungsi pada asm Z80 , yang menggambar piksel poligon demi piksel dan tanpa lubang saat menghubungkan poligon.


Halo segitiga!

Partikel



Karena adanya generator label garis layar, saya menulis prosedur keluaran titik agak melengkung dan lambat menggunakan label ini. Prosedur memiliki dua titik masuk - hanya kebalikan dari piksel, dan kebalikan dari piksel dengan mengisinya dengan TINTA + CERAH + dan warna yang ditentukan dalam salah satu register.

Pada tahap menciptakan efek dengan partikel, saya menemukan bahwa contoh dengan struktur dari contoh di wiki sjAsm tidak berfungsi. Googling mengangkat topik dari situs zx-pk.ru , tempat masalah ini dijelaskan, dan tidak ada solusi - ha, baik - masalah lain.

Saya memutuskan untuk melakukan semuanya dengan jelas - memperbarui koordinat terlepas dari render, dengan gangguan. Ya ... ditambah byte untuk menghasilkan tabel interupsi.

Ada beberapa partikel pada tahap ini, dan mereka hampir tidak masuk ke dalam bingkai - ini adalah tentang lambatnya prosedur saya untuk menghasilkan titik%)) Tapi menggunakan meja bersama dengan sprite tidak membiarkan saya membuangnya dan membawanya siap, karena ruang yang sangat dihemat ini hanya membutuhkan satu generator tabel. Dan cintaku untuk sepeda juga :)

Terlalu sedikit partikel ... menambah jumlahnya, tetapi sekarang rendering telah digemukkan menjadi dua bingkai.


Menguji Peters WS64 , yang saya dapatkan di cc terakhir dan diperbaiki musim dingin ini :)

Ngomong-ngomong, sudah pada tahap ini titik berubah menjadi titik horizontal tebal 2: 1 , seperti pada Commodore 64 . Ini terjadi karena jumlah partikel yang awalnya kecil, dan ketidakpuasan saya dengan fakta bahwa mereka sangat tidak terlihat ketika dijalankan dalam kehidupan nyata. Mengatasi masalah dengan mengganti pelat

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

pada

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

yang memperburuk keakuratan penentuan posisi dan membuat penerbangan sedikit tersentak-sentak, tetapi meningkatkan visibilitas. Di sini, ia juga memainkan ke tangan bahwa partikel-partikel jatuh dari atas ke bawah - penglihatan mereka dioleskan secara vertikal.

Partikel-partikel secara kebetulan jatuh masing-masing dengan kecepatan acaknya sendiri, dan dua byte digunakan untuk menyimpan koordinat Y.

Sprite

Saya membuang bagian sprite yang belum selesai, menyadari bahwa saya tidak bisa cocok dengan itu.

Selain itu, sudah ada kekurangan ruang, jadi saya ingat tentang artikel hebat Introspek tentang pengemasan, saya memilih zx7 sebagai pengemas, yang menghemat sekitar 110 byte. Omong-omong, mungkin seseorang tahu pengepak yang lebih cocok untuk intro 1k?

Konstruksi kekacauan



Karena saya sudah memiliki prosedur untuk mengeluarkan poligon, sepertinya ide yang bagus untuk membagi logo cc menjadi poligon dan menampilkannya satu per satu.

Saya menulis beberapa kode uji yang menampilkan beberapa poligon - semuanya berfungsi sesuai yang saya maksud - baik-baik saja.

Untuk memeriksa apakah ide saya cocok atau tidak dalam 1k , dihasilkan sejumlah poligon acak tertentu, menurut perkiraan, jumlah yang cukup untuk logo tersebut, dan membawanya ke sumber. Dikompilasi, dan memastikan bahwa - sangat baik - intro, dalam bentuk ini, cocok dengan batas 1024 byte.


Foto kehidupan, apakah Anda mengenali perangkat di atas meja? :)))

Saya memutuskan untuk sekali lagi menguji intro setengah jadi, sudah dengan poligon, dan pengepak, diunggah ke nyata dan ... mendapat reset. Pertama-tama, saya mulai berdosa bahwa saya lupa menginisialisasi memori di suatu tempat, dari mana, di mana semuanya bekerja dengan baik pada emulator 0x00 , dalam kehidupan nyata ada sampah yang menyebabkan reset.

Tidak ada yang lebih baik untuk menemukan tempat masalah daripada metode setengah divisi dan berhenti saya tidak bisa datang dengan.

Dibawa dengan reset secara real selama dua jam, tidak ada cara untuk melokalisasi kesalahan ...
Ternyata, itu tidak ada dalam kode saya, itu termasuk penambah suara yang disertakan pada ponsel dari mana saya memuat WAV. Perbaikan dari aliran sedikit dalam file WAV menghasilkan aliran delirium.

Segera setelah saya mematikannya, semuanya bekerja secara ajaib.

Dia menjabarkan logo dalam editor grafis greenpixel kesalahan , memecahnya menjadi banyak segitiga, dan secara manual mengarahkan koordinat ke sumber. Setelah mengisi logo Chaos Constructions sepenuhnya dan menjalankannya dalam kehidupan nyata - saya senang - itu terlihat cukup bagus.


Tampilan logo pertama di nyata

Namun, saya memasukkan poligon acak terlalu sedikit, dan pada logo asli, ada batas 1k per 150 byte. Dan ini terlepas dari kenyataan bahwa efek partikel masih belum selesai, dan transisi antara bagian-bagian itu tajam.

Untuk pergi tidur hari itu, karena keributan dengan gangguan, ternyata sedini 8 pagi. 8)

Dan ya, saya mencoba untuk mengoptimalkan ukuran dengan menyimpan koordinat dan indeks titik secara terpisah, tetapi pengepakan tidak terlalu menyukainya, yang membuat ukuran hanya meningkat.

Terakhir



Saya datang dengan cara diversifikasi output logo, untuk ini butuh hampir tidak ada tapi dua label piksel lagi:

 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 

Itu memberikan efek keren meningkatkan detail rendering logo, atau kurangnya detail awal dan peningkatan ketajaman secara bertahap.

Dan akhirnya, saya membuat versi final dengan semua transisi, membuang banyak segalanya. Dalam prosesnya, saya menemukan kesalahan dalam prosedur menggambar segitiga - jika dua simpul memiliki koordinat Y yang sama, maka segitiga tersebut digambar bengkok (sepertinya membaginya dengan 0 saat menghitung dx ), dilewati dengan hack sementara.


Menguji versi final di Leningrad 48

Optimalisasi ukuran


Digit ganda adalah "byte tambahan"

94 byte tambahan ...

Waktunya telah tiba untuk menghentikan pelestarian / pemulihan β€œbudaya” dari register prosedur input / output, jauh dari mana-mana hal itu diperlukan, tetapi ingatannya memakan.

86 byte ...

Diuji dalam kehidupan nyata - itu berhasil! Dia menghabiskan sedikit lebih banyak memori, sekaligus memperbaiki bug yang dibagi 0 - 63 byte!

57 byte ...

Menambahkan perulangan.

 random_store: start: 

Looping dengan cara ini dilakukan pada tingkat pembongkaran, sebagai sebagai sumber entropi untuk RNG , beberapa byte dari kode inisialisasi digunakan (untuk menghemat ruang), yang dimanjakan oleh RNG pada bagian pertama. Oleh karena itu, untuk pengulangan, setelah akhir intro, ada ret , well, dan kemudian membongkar dan beralih ke kode yang belum dibuka ...

Itu tidak mungkin untuk menyingkirkan 48 byte terakhir, saya harus memotong penangan interrupt, tetapi Hore! Diisi! Bahkan 1 byte tambahan tetap.

Dan karena tidak ada gangguan, itu dapat dinilai untuk frame, dan sulit untuk melihat penampang balok pada satu piksel pada efek pertama, jadi saya meningkatkan jumlah partikel per mata, dengan kompromi antara kecepatan dan hiburan.

Menyengat lebih keras, dengan bodohnya memindahkan kode dan data dari satu tempat ke tempat lain, membantu pengepak. Yang butuh waktu :)

Ini membebaskan sekitar 10 byte di mana saya terjebak parodi suara. Khk, khe, suara - ini ada di beberapa tempat, dengan memasukkan telinga:

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

Saya tidak "memaku" suara, tetapi membuat definisi, sehingga mendapatkan dua versi intro, dengan dan tanpa suara. Dalam hal itu tanpa suara, dalam byte "ekstra" berdesakan

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

Saya mengumpulkan trd dan ketuk , dan mengunggah semuanya ke situs web cc .

Hore - Saya berpartisipasi dalam demopati!

Kata penutup

Ternyata menjadi lucu dengan suara itu, seseorang di patlace mengatakan "suara jernih", seseorang menatapku dengan aneh, dan pada pouet aku menemukan yang berikut:



Dan ini:



Secara umum, saya tidak mengerti apakah ada yang menyukai suara 10-byte atau tidak :)

Dan yang terakhir - itu memalukan bahwa kompetisi 1k tidak terjadi tahun ini, pekerjaannya ternyata layak, menurut saya, tetapi sulit untuk bersaing dengan 640k , tetapi saya benar-benar ingin bersaing.

Tulis demo, tulis 1k!

Dan inilah yang akhirnya (ps, jaga telingamu):



Versi Diam:

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


All Articles