1 poin oleh GN⁺ 2024-09-14 | 1 komentar | Bagikan ke WhatsApp
  • Untuk menjalankan game engine Trial di Nintendo Switch, runtime Common Lisp SBCL telah di-porting selama 2 tahun, dan saat ini sudah mencapai tahap dapat mengompilasi serta menjalankan kode Lisp di Switch, termasuk integrasi dengan shared library
  • Switch memiliki lingkungan ARM64 Cortex-A57 4-core, RAM 4GB, tetapi tidak memiliki shell, command line, atau compiler, dan pembuatan halaman yang dapat dieksekusi juga diblokir, sehingga tidak cocok dengan metode bootstrap SBCL yang umum
  • Build menggabungkan host Linux ARM64 dan Nintendo SDK; core dipisahkan menjadi kode dan data menggunakan fasteval, immobile-code, dan elfination, lalu dikemas menjadi paket final
  • Contoh REPL Trial di devkit Switch menjalankan konteks OpenGL, pemrosesan input, hingga alokasi shader, tetapi crash saat garbage collector berjalan, dan audio belum memungkinkan karena masalah callback C
  • Pekerjaan utama yang tersisa adalah menstabilkan safepoint untuk GC multithread, memulihkan callback C, menghindari kompilasi runtime CLOS, serta optimasi performa; sebagian kode tidak dapat dipublikasikan karena NDA Nintendo

Sejauh mana SBCL berjalan di Switch

  • Untuk menjalankan game engine Trial di Nintendo Switch, porting SBCL telah dikerjakan bersama Charles Zhang selama dua tahun terakhir
  • Tantangan utamanya adalah menyesuaikan runtime Common Lisp yang berjalan di bawah Trial dengan platform Switch
  • Hal yang saat ini sudah mungkin dilakukan:
    • Runtime dan compiler telah di-porting sehingga kode Lisp arbitrer dapat dikompilasi dan dijalankan langsung di Switch
    • Dapat berinteraksi dengan shared library
    • Berbagai library portabilitas sistem operasi yang dibutuhkan Trial di Switch juga telah di-porting
  • Contoh REPL Trial berjalan di devkit Switch
    • Karena Switch sendiri tidak memiliki terminal, Trial membuat konteks OpenGL, mengelola input, mengalokasikan shader, dan menampilkan teks di layar
  • Bagian yang masih buntu:
    • SBCL segera crash saat mencoba menjalankan garbage collector
    • Masih ada bagian yang belum dapat diakali karena batasan khas Switch
    • Mekanisme callback C rusak, sehingga output audio tidak memungkinkan
    • Mungkin masih ada masalah lain terkait performa yang belum terlihat

Biaya dan keberlanjutan

  • Pekerjaan porting sejauh ini telah menghabiskan sekitar 17.000 dolar AS, dan biaya dibayarkan kepada Charles Zhang secara bulanan
  • Pendapatan berasal dari penjualan Kandria serta dukungan di Patreon, GitHub Sponsors, dan Ko-Fi
    • Pada bulan yang baik, sekitar 1.200 dolar AS
    • Pada bulan yang buruk, sekitar 600 dolar AS
  • Sulit hidup hanya dari pendapatan ini di Zürich, Swiss, dan saat ini penulis bertahan dengan tinggal bersama orang tua serta mengurangi pengeluaran pribadi
  • Karena meragukan apakah penjualan Kandria untuk Switch dapat menutup biaya porting, menjadi sulit menentukan ke mana sumber daya terbatas harus dialokasikan
  • Pendapatan dukungan untuk sementara akan digunakan untuk porting SBCL ke Switch dan proyek game rahasia yang sedang dikerjakan

Lingkungan Switch dan syarat porting

  • Lingkungan Switch yang diketahui secara publik:
    • Kode pengguna berjalan di chip ARM64 Cortex-A57
    • Menggunakan 4 core dan RAM 4GB
    • Berjalan di atas sistem operasi microkernel proprietary yang pertama kali dikembangkan untuk Nintendo 3DS
  • SBCL sudah memiliki port ARM64 Linux, sehingga dari sisi code generation sudah terselesaikan
  • Kandria mudah masuk ke RAM 4GB, jadi kapasitas memori itu sendiri bukan masalah
  • Kesulitan sebenarnya ada pada antarmuka dengan sistem operasi proprietary Switch
    • Ada batasan yang tidak ada pada sistem operasi PC umum
    • Ini terutama menjadi masalah bagi sistem seperti Lisp
  • Switch adalah satu-satunya konsol yang mendukung rendering OpenGL, yang menjadi basis Trial
    • Xbox hanya mendukung DirectX, tetapi diketahui ada layer OpenGL → DirectX yang dikembangkan Microsoft, sehingga mungkin ada peluang
    • Playstation diketahui memiliki API grafis yang sepenuhnya proprietary, sehingga tetap menjadi platform yang tidak ingin dipertimbangkan untuk porting
  • Untuk pengembangan, akses diperoleh dari Nintendo of Europe, dan devkit seharga sekitar 400 dolar AS dibeli
  • Devkit dan SDK hanya berjalan di Windows, yang kemudian menambah beban pada proses build

Build SBCL umum dan benturannya di Switch

  • SBCL sebagian besar ditulis dalam Lisp itu sendiri, dan juga menyertakan runtime C kecil
  • Runtime C dibangun dengan compiler C biasa, tetapi perlu mengetahui informasi tentang lingkungan sistem operasi target
  • Karena runtime itu sendiri tidak memiliki compiler Lisp, bootstrap SBCL membutuhkan implementasi Lisp lain, idealnya menggunakan versi SBCL lain
  • Build 5 tahap di PC

    • build-config
      • Mengumpulkan opsi konfigurasi build untuk target dan mengeluarkannya dalam format yang dapat dibaca tahap build berikutnya
    • make-host-1
      • Membangun cross-compiler dengan compiler Lisp host
      • Juga menghasilkan file header yang mendeskripsikan layout memori objek Lisp sebagai struct C
    • make-target-1
      • Membuat runtime C dengan compiler C target
      • Runtime C mencakup garbage collector dan kode perekat dengan lingkungan sistem operasi
      • Juga menghasilkan konstanta dari header sistem operasi yang perlu diketahui compiler Lisp target dan runtime
    • make-host-2
      • Membangun sistem Lisp target, yaitu compiler dan standard library, menggunakan cross-compiler Lisp yang dibuat di make-host-1
      • Menghasilkan cold core yang dapat dimasuki oleh runtime
    • make-target-2
      • Memuat cold core ke runtime target dan menyelesaikan bootstrap
      • Setelah sistem Lisp dimuat ke memori, ia di-dump sebagai warm core
      • Setelah itu, kode baru dapat dimuat dan image baru dapat di-dump dengan bebas
  • Titik bermasalah di Switch

    • Build SBCL membutuhkan tahap menjalankan kode Lisp di mesin target
    • Kode Lisp pengguna tidak dapat ditangani hanya dengan kompilasi batch sederhana seperti C, dan saat dieksekusi diasumsikan berada di lingkungan target
    • Distribusi aplikasi juga mirip dengan make-target-2: kode Lisp dikompilasi secara bertahap lalu core yang ditempeli runtime di-dump
    • Saat startup, runtime SBCL memetakan blob core ke memori, menandai halaman kode sebagai executable, lalu melompat ke fungsi entry kustom
    • Di Switch, seluruh cara ini menjadi masalah

Strategi build untuk Switch

  • Switch bukan lingkungan PC dan tidak memiliki shell, command line, atau toolchain compiler
  • Karena sistem operasi tidak mengizinkan pembuatan halaman executable, kompilasi inkremental Lisp biasa tidak mungkin dilakukan meskipun tahap build dapat dijalankan di Switch
  • Sebagian besar kode bersifat platform-independent, sehingga dapat dikompilasi untuk ARM64
  • Hanya bagian yang menyentuh lingkungan sistem operasi sekitar yang perlu dibuat tahu bahwa targetnya adalah Switch, dan implementasinya dapat dibuat di lingkungan ARM64 lain seperti Linux
  • Tahap build untuk Switch

    • build-config
      • Dijalankan di sistem host dengan flag khusus yang menandakan build Switch
      • Mengaktifkan contrib fasteval
      • Karena runtime compilation tidak dapat dilakukan di Switch, fasteval menggantikan titik yang membutuhkan pemanggilan compiler
    • make-host-1
      • Tidak banyak perubahan, dan menghasilkan header untuk persiapan platform Switch
    • make-target-1
      • Melakukan cross-compile runtime C untuk Switch dengan compiler C yang disediakan Nintendo SDK
      • Karena Switch OS tidak kompatibel dengan POSIX, target runtime kustom dibuat untuk SBCL, dan perbedaan sistem operasi seperti dynamic linking serta page mapping di-stub atau dibungkus
    • build-config, make-host-1, make-target-1 kedua
      • Membuat sistem ARM64 Linux biasa dengan feature set yang sama seperti Switch
      • Beberapa proses Lisp menggunakan flag khusus untuk memberitahukan bahwa target finalnya adalah Switch
    • make-host-2, make-target-2
      • Mendapatkan build SBCL untuk Linux ARM64 yang agak khusus, lalu mengompilasi kode pengguna setelahnya
    • Kompilasi kode pengguna
      • Memodifikasi *features* agar sistem percaya sedang berjalan di Switch, bukan Linux
      • Menyertakan :nx dan mengecualikan :linux, :unix, :posix
      • Setelah menonaktifkan ASDF, program seperti Trial dikompilasi sedekat mungkin dengan cara biasa dan core baru di-dump

Memaketkan core dengan immobile-code dan elfination

  • Karena strategi pemetaan core biasa tidak dapat digunakan di Switch, cara menempelkan core baru ke runtime Switch tidak berjalan
  • Sebagai solusi, digunakan fitur SBCL yang relatif kurang dikenal, yaitu immobile-code dan elfination
  • SBCL biasa menaruh kode yang dikompilasi saat runtime ke halaman tertentu dan menandai halaman itu sebagai executable
    • Jika kode tidak lagi dibutuhkan nanti, kode itu dapat menjadi target garbage collection
    • Ruang dapat direklamasi dan sisa kode dapat dikompaksi
  • immobile-code menggunakan strategi lain
    • Kode ditempatkan pada halaman kode yang dipesan khusus dan tetap berada di sana
    • Kode tidak dapat di-garbage-collect
    • Sebagai gantinya, dukungan executable tradisional dari sistem operasi dapat dimanfaatkan
    • Executable memiliki section yang telah ditandai sebelumnya dan dikenali OS sebagai kode, dan saat program dimulai OS menangani pemetaannya
  • Tahap elfination mengubah core menjadi section kode dan data terpisah yang diperlukan oleh executable biasa
    • elfinator menganalisis core
    • Assembly ditulis ulang agar menjadi position-independent code yang diperlukan untuk address space layout randomization
    • Dipisahkan menjadi file assembly kode murni dan file payload data murni
  • Tahap final:
    • Membuat file assembly dengan elfinator
    • Menautkan binary final
    • Dengan authoring tool dari Nintendo SDK, metadata, shared library, aset, dan binary aplikasi digabungkan menjadi satu paket final

Infrastruktur build dan cakupan yang dapat dipublikasikan

  • Build setidaknya membutuhkan mesin ARM64 Linux untuk menjalankan sebagian besar proses build
  • Untuk menjalankan compiler Nintendo SDK dan authoring tool, dibutuhkan mesin AMD64 Windows atau mesin AMD64 Linux yang menggunakan Wine
  • Konfigurasi sebenarnya mendekati total tiga mesin
    • AMD64 “driver”
    • Host build ARM64
    • VM Windows yang berkomunikasi dengan devkit
  • Sistem build khusus dengan caching dan logika sinkronisasi antar-mesin ditulis untuk otomatisasi
    • Karena juga harus dapat berjalan di lingkungan MSYS2/Windows, ada masalah konversi path
  • elfinator dan immobile-code dibuat berjalan di ARM64, dan library pendukung seperti pathname-utils, libmixed, serta cl-gamepad juga di-porting
  • Karena NDA Nintendo, banyak detail tidak dapat dipublikasikan
  • Pekerjaan yang bisa dipublikasikan telah di-upstream, dan library Lisp tidak memiliki private fork
  • Agar tidak terhubung langsung dengan Nintendo SDK, dibuat library C terpisah, dan library Lisp mengakses fungsi sistem operasi melalui antarmuka kustom ini
    • Ini adalah struktur untuk memublikasikan sisi Lisp dan hanya menjaga library C kecil tetap privat

Pointer absolut dan relokasi saat load

  • Elfination sejak awal bukan fitur yang dirancang untuk membuat kode Lisp executable yang position-independent
  • Kode Lisp biasanya berisi banyak pointer absolut
  • Diperlukan pekerjaan pada compiler dan runtime SBCL untuk mendukung relokasi pointer absolut saat load
  • Objek kode biasanya berisi konstanta kode, dan harus dibuat agar tidak lagi memiliki pointer absolut
    • GC tidak dapat memodifikasi section executable
    • OS loader juga tidak dapat memodifikasi section executable untuk relokasi pointer absolut
  • Cara penyelesaiannya:
    • Pointer absolut seperti konstanta kode dipindahkan ke ruang baca/tulis di luar area text
    • Referensi konstanta di dalam kode ditulis ulang agar memuat dari ruang baca/tulis ini
    • Loader dan moving GC dapat memodifikasi pointer di ruang tersebut

Masalah garbage collector dan safepoint

  • GC standar SBCL adalah gencgc, yaitu garbage collector generasional
  • gencgc memisahkan generasi objek untuk dipindai pada frekuensi berbeda, dan mengompaksi ruang dengan menyalin objek ke lokasi generasi lain
  • Struktur ini sendiri tidak menjadi masalah mendasar di Switch, tetapi multithreading menimbulkan masalah
  • Jika ada beberapa thread, satu thread mungkin sedang mengakses objek, sehingga objek tidak dapat dipindahkan sembarangan
  • Solusi termudah adalah menghentikan semua thread sebelum GC dimulai
  • Perbedaan Unix dan Switch

    • Pada sistem Unix, mekanisme signal dapat digunakan untuk mengirim sinyal ke thread lain agar park
    • Switch tidak memiliki mekanisme signal, dan thread juga tidak dapat di-interrupt
    • Setiap thread harus dibuat menyadari sendiri bahwa ia perlu park, dan strategi umumnya adalah safepoint
    • Safepoint membuat compiler menyisipkan kode tambahan agar thread memeriksa apakah perlu park
    • Karena menambahkan pemeriksaan memiliki biaya, jumlahnya harus dibuat sesedikit mungkin
    • Jika pemeriksaan terlalu jarang, GC tidak dapat dimulai sampai semua thread park, sehingga thread lain berhenti
    • Jika pemeriksaan membutuhkan banyak instruksi, hal itu mengganggu cache line CPU dan optimasi pipelining
  • Batasan safepoint SBCL yang ada

    • Sistem safepoint SBCL saat ini ditulis untuk Windows
    • Windows juga tidak memiliki signal handler antar-proses, tetapi berbeda dari Switch, Windows memiliki signal handling untuk thread saat ini
    • Cara yang ada:
      • Setiap thread mempertahankan halaman tempat safepoint menulis satu word
      • Saat GC dimulai, halaman itu ditandai read-only
      • Jika thread lain mencapai safepoint dan mencoba menulis ke halaman, segmentation fault terjadi dan thread tersebut park
      • Ini efisien karena hanya membutuhkan satu instruksi write
    • Di Switch, teknik ini juga tidak dapat digunakan, sehingga pemeriksaan yang lebih rumit harus disisipkan
    • Karena safepoint tidak dibutuhkan di platform selain Windows, bagian ini belum diuji di tempat lain, dan tidak stabil terlepas dari modifikasi untuk Switch
    • Bagian tersebut di codebase mungkin perlu dibersihkan besar-besaran, tetapi harapannya tidak sampai perlu penulisan ulang total

Menghindari kompilasi runtime CLOS

  • CLOS biasanya menunda kompilasi discriminating function yang diperlukan untuk dispatch method sampai pemanggilan pertama generic function
  • CLOS sangat dinamis, dan method dapat ditambahkan atau dihapus hampir kapan saja, sehingga sulit mengetahui kapan sistem sudah selesai
  • Di Switch, compiler tidak dapat dipanggil, sehingga pola kompilasi tertunda ini tidak dapat digunakan apa adanya
  • Strategi saat ini adalah bergantung pada fast evaluator
    • Fungsi compile di-stub
    • Sebagai ganti kompilasi, dibuat lambda yang menjalankan kode dengan evaluator
    • Ini juga berjalan untuk kode pengguna yang bergantung pada compile
    • Kecepatan eksekusinya jauh lebih lambat daripada kompilasi sungguhan

Pekerjaan tersisa dan risiko performa

  • Pendekatan fasteval terutama adalah fallback
  • Ingin mengeksplorasi cara membekukan sebanyak mungkin state CLOS dan melakukan pre-compile kode sebanyak mungkin tepat sebelum image final di-dump
  • Mode block compilation yang dipulihkan Charles beberapa tahun lalu juga akan diteliti lebih lanjut
  • Karena prosesor Switch relatif lemah, optimasi tambahan mungkin diperlukan
    • Di sisi engine Trial
    • Di sisi kode Kandria
  • Sejauh ini, karena komputer 10 tahun lalu pun dapat menangani kebutuhan game dengan cukup, optimasi relatif sedikit sudah memadai
  • Pekerjaan berprioritas tinggi:
    • Membuat garbage collector berjalan sepenuhnya
      • Saat ini sudah bisa boot dan masuk hingga main loop Trial
      • Gagal saat mencapai multi-generation compaction
    • Membuat callback dari C berjalan kembali
      • Bagian terkait di codebase SBCL memiliki banyak routine assembly manual
      • Mungkin perlu disesuaikan dengan immobile-code dan elfination
      • Trial hanya membutuhkan callback untuk pemutaran suara melalui libmixed
    • Pekerjaan fitur portabilitas tambahan yang diperlukan sebelum selftest suite Trial sepenuhnya lulus di Switch

Cakupan publikasi yang dibatasi NDA

  • Ingin mempublikasikan seluruh pekerjaan porting, tetapi tidak dapat melakukannya karena NDA Nintendo
  • Bagian yang dapat dipublikasikan telah di-upstream atau dipublikasikan
  • Sebagian kode yang terhubung langsung dengan Nintendo SDK tidak dapat dibagikan kepada orang yang belum menandatangani NDA
  • Jika ada yang ingin merilis game Common Lisp di Nintendo Switch, mereka dapat memperoleh akses ke pekerjaan porting setelah menandatangani NDA
  • Dalam pembaruan bulanan untuk Patron, perkembangan akan dibagikan secara lebih terperinci

1 komentar

 
GN⁺ 2024-09-14
Komentar Hacker News
  • Selama beberapa minggu terakhir saya mencoba pengembangan game dengan Common Lisp menggunakan Trial(https://github.com/Shirakumo/trial), dan rasanya sangat menyenangkan
    Kemampuan untuk mengubah hampir semua elemen saat game sedang berjalan adalah keunggulan yang sangat besar, jadi saya berharap porting ini berhasil

    • Bahasa keluarga Lisp tampaknya cocok untuk membuat game. Kemampuan untuk mengevaluasi kode secara interaktif tanpa kompilasi ulang membuat perbedaan besar dalam pengembangan fitur, pengembangan bertahap, dan perbaikan bug
      Kemampuan mempertahankan state aplikasi di antara perubahan kode juga tampak sangat berguna, dan Common Lisp juga terlihat jauh lebih cepat daripada yang saya bayangkan secara samar
      Secara pribadi, bukan hanya untuk pengembangan game, kekurangan terbesarnya secara umum adalah penggunaan struktur data, terutama cara menangani map yang terasa kaku, tetapi kompromi itu tampaknya layak diterima
  • Ini benar-benar keren. SBCL adalah implementasi bahasa yang hebat, dan saya memang ingin mencoba pengembangan Common Lisp di konsol game “sungguhan”
    Fakta bahwa Shinmera yang mengerjakan ini juga mengejutkan dalam arti baik. Dulu saya pernah beberapa kali melihatnya di #lispgames dan Lisp Discord, tetapi tidak tahu bahwa ia juga tertarik pada pengembangan tingkat rendah seperti ini
    Saya pernah sekilas melihat bagian dalam SBCL lalu mundur karena gentar, jadi ini terasa makin mengesankan. Saya juga penasaran apakah kombinasi SBCL dengan threading dan SDL2 sekarang berjalan di Raspberry Pi

    • Pekerjaan di sisi SBCL bukan saya yang melakukan; itu seluruhnya pekerjaan Charles, yang saya pekerjakan untuk ini. Bagian saya adalah portabilitas agar Trial berjalan di berbagai lingkungan, struktur build keseluruhan, dan stub runtime awal
      Dan seperti yang sudah disebutkan sebelumnya, *her :)
    • Bukankah “her” yang benar?
  • Terima kasih kepada penulis yang telah menulis artikel yang menarik dan terperinci. Detail porting konsol resmi pada tingkat seperti ini biasanya baru terasa terungkap beberapa tahun setelah umur konsolnya berakhir
    Membaca pekerjaan sedalam ini kadang membuat saya iri, sambil teringat pekerjaan saya sendiri yang seharian memakai perangkat lunak repetitif

    • Berdasarkan masa ketika saya bekerja di bidang itu, alat resmi seperti ini pun biasanya cukup tambal sulam dan bersifat sementara; kecuali untuk dukungan debugging, toolchain homebrew modern untuk platform lama sering kali lebih baik
      Devkit biasanya memiliki hook yang lebih bagus, tetapi pada saat yang sama ada juga keuntungan karena dapat menghindari alur yang berpusat pada GDB. Setelah mengalami keduanya, saya tidak yakin dunia itu sampai sebegitu patut membuat iri
    • Saya baru saja hendak memulai satu hari lagi dengan Ruby on Rails, jadi saya sedang memikirkan hobi atau proyek open source apa yang kelak layak saya curahi perhatian
      Mungkin bukan proyek yang membutuhkan perhatian saya, melainkan proyek yang akan dibutuhkan oleh perhatian saya nanti :D
  • Melihat bagian “saya ingin membuka semuanya, tetapi tidak bisa karena NDA”, saya jadi penasaran mengapa mereka memakai SDK resmi alih-alih SDK homebrew(https://switchbrew.org/wiki/Setting_up_Development_Environment) yang tanpa batasan
    Sepenuhnya spekulasi, mungkin karena Nintendo tidak mengizinkan perilisan resmi game yang dibuild dengan SDK pihak ketiga

    • Game yang dibuat sebagai homebrew tidak bisa dirilis dan harus memakai SDK resmi. Selain itu, sangat sedikit orang yang memiliki Switch yang sudah di-jailbreak, sehingga selain lewat emulator, menjalankan gamenya pun menjadi sangat sulit
  • Terkait dengan ini ada https://opengoal.dev
    Sebagai latar belakang, Naughty Dog memakai bahasa internal mirip Lisp bernama GOAL saat membuat seri Jak & Daxter untuk PS2. Karena mereka meninggalkan cukup banyak informasi debugging, reverse engineering menjadi mungkin, dan proyek OpenGOAL berhasil melakukannya
    Sekarang game-game ini bisa dijalankan di semua platform yang sudah dipasangi port compiler GOAL. Sejauh yang saya tahu saat ini baru sekitar x86, dan akan keren kalau di-port ke Switch

  • Saya baru saja membeli Kandria. Saya bukan tipe yang banyak bermain game, jadi mungkin tidak akan banyak memainkannya, tetapi menurut saya Shinmera jelas sedang memperluas batas dunia Lisp dan layak didukung

  • Karyanya benar-benar luar biasa. Sebagai seseorang yang kadang memakai Common Lisp, pekerjaan seperti ini membuat saya sangat senang

  • Saya berharap perusahaan seperti Nintendo atau Sony mau mendukung langsung upaya semacam ini. Pada akhirnya ini adalah cara lain untuk membuat game konsol, yaitu IP, dan saya tidak tahu apa kerugiannya jika di tingkat platform mereka memulai sesuatu seperti Github Accelerator

    • Sudah jelas bahwa developer game akan melewati prosedur apa pun yang diminta pemilik platform dengan biaya sendiri. Saat menentukan akan merilis di platform mana, developer tidak punya banyak daya tawar untuk bersikap cerewet soal detail teknis
      Nintendo tidak perlu membuat insentif baru untuk mendorong perilisan di Switch. Mereka sudah punya insentif terbesar: lebih dari 140 juta unit terjual dan tingkat pembelian game yang tinggi
      Meski begitu, prosedurnya tidak sebanyak dulu. Sistem masa kini sebagian besar sudah mengerucut ke arsitektur CPU dan GPU serbaguna, dan kalaupun ada perbedaan, sering kali hanya seperti ornamen kecil
    • Dulu dukungan seperti itu memang ada, tetapi yang dilakukan orang kebanyakan adalah mem-port MAME dan emulator lain, atau menyalin game era 8-bit dan 16-bit
      Karena itulah hal-hal bagus jadi sulit dinikmati
  • Saya datang ke HN untuk membaca tulisan seperti ini. Tepuk tangan untuk penulis asli dan rekannya. Saya tahu itu mustahil, tetapi akan menjadi berkah besar kalau Nintendo memperlakukan sistemnya sedikit lebih terbuka

  • Karena tidak dijelaskan di mana pun, saya tambahkan: SBCL adalah “Steel Bank Common Lisp”
    “Steel Bank Common Lisp(SBCL) adalah compiler Common Lisp berkinerja tinggi. Ini adalah perangkat lunak open source/bebas dengan lisensi permisif, dan selain compiler serta runtime system untuk ANSI Common Lisp, juga menyediakan lingkungan interaktif yang mencakup debugger, statistical profiler, alat code coverage, dan berbagai ekstensi”
    https://www.sbcl.org/