Pembuatan: Inti kerajinan



Harga
Deskripsi Produk Pembuatan: Inti kerajinan

Saat memporting dan menulis ulang ‘Craft’ untuk digunakan sebagai inti libretro, kami memutuskan akan bagus untuk mendokumentasikan beberapa langkah yang terlibat untuk tujuan pendidikan.

Anda dapat memeriksa repositori kode sumber kami di sini.

Mungkin ada addendum dan tindak lanjut untuk artikel ini nanti. Perhatikan bahwa beberapa langkah ini bukanlah hal-hal yang 'wajib' dilakukan untuk tujuan memporting perangkat lunak ke API libretro, mereka hanyalah praktik terbaik berdasarkan materi pelajaran di tangan.

Langkah 1 - Dapatkan itu dikompilasi
‘Craft’ menggunakan Cmake sebagai sistem build-nya. Meskipun libretro tidak menempatkan persyaratan untuk membangun sistem yang Anda gunakan untuk proyek Anda, biasanya karena kebiasaan dan preferensi, kami lebih suka menulis Makefile statis untuk kenyamanan dan portabilitas.

Kami menggunakan kembali template Makefile dasar untuk ini yang kami impor ke proyek lain. Ketiga file yang akan kita buat adalah: Makefile.libretro, link.T, dan Makefile.common. Kami akan menempatkan file-file ini ke dalam akar proyek (atau tempat lain di mana Makefile pusat biasanya disimpan).

Agar lebih mudah dipahami, Makefile.libretro adalah solusi Makefile umum yang mencakup Makefile.common. Makefile menyiapkan semua target platform yang didukung oleh inti Anda, sementara Makefile.common setara dengan CMakeLists.txt. Anda mendefinisikan semua file di sini yang perlu dikompilasi di sini.

Sebuah rundown pada beberapa variabel di dalam Makefile.common:

SOURCES_C - Anda menambahkan file kode sumber C ke variabel ini.

SOURCES_CXX - Anda menambahkan file kode sumber C ++ ke variabel ini.

INCFLAGS - Anda menambahkan menyertakan direktori ke varaible ini.

Craft adalah program C-only, jadi kami akan menambahkan semua file sumber ke SOURCES_C.

Pertama kita akan mencoba untuk mengkompilasi sebanyak mungkin file sebelum kita akan melanjutkan untuk benar-benar membuatnya bekerja dengan libretro. Kemudian, kami mungkin mengganti beberapa dependensi yang digunakan ‘Kerajinan’ dengan beberapa milik kami sendiri untuk alasan portabilitas dan konsistensi. Beberapa dependensi yang akan kami hindari untuk saat ini seperti glew dan glfw, kami akan menambahkan pengganti kami sendiri untuk ini nanti.

Anda akan melihat setelah mengikuti commit ini bahwa masih ada sejumlah referensi tidak jelas yang tersisa sebelum inti benar-benar akan dirakit. Itu karena beberapa dependensi yang telah kita hilangkan sejauh ini (seperti glew dan glfw), dan karena kita belum menulis implementasi libretro.

Berikut ini adalah catatan berdasarkan ketergantungan yang ditemukan di Craft, jika Anda tidak menemukan salah satu dependensi ini di proyek lain, Anda tidak perlu khawatir tentang hal ini.

CATATAN: Saya mendefinisikan SQLITE_OMIT_LOAD_EXTENSION dan menambahkannya ke CFLAGS karena kami tidak memerlukan fungsionalitas seperti itu untuk port libretro.

CATATAN 2: Meskipun pengembang Craft telah berusaha keras untuk memastikan ada beberapa dependensi keras yang mungkin (dan sedikit yang ada, memiliki sumber mereka yang disediakan di dalam basis kode proyek), masih ada beberapa dependensi keras yang akan mengharuskan kita untuk menarik beberapa sumber nanti, seperti 'libcurl'. Kami akan mengabaikan ini untuk saat ini, dan hanya secara dinamis menautkannya untuk sekarang sampai kita dapat menyingkirkan ketergantungan ini dengan mengumpulkannya ke dalam inti itu sendiri.


Langkah 2 - Aplikasi Skeleton libretro
Kami akan menambahkan file sumber libretro skeleton sekarang ke proyek. Kami akan menambahkan file-file ini ke direktori ‘src’:
- libretro.c
- libretro.h

Ini akan menjadi file program utama dari inti libretro kami. Berbeda dengan program normal, main () bukan entry point default. Dalam inti libretro, tidak ada titik masuk default dan sebagai gantinya Anda menjalani siklus hidup program libretro untuk inisialisasi dan deinitialisasi program. Kami akan kembali ke ini nanti.

Sebagian besar fungsi saat ini adalah bertopik yang disengaja. Kami akan mulai mengisinya nanti.

CATATAN: Karena 'Craft' adalah program yang tidak memerlukan konten untuk dijalankan (seperti di - Anda tidak perlu memberikannya dengan mengucapkan ROM atau file gambar agar dapat dimulai), kami ingin inti libretro untuk memulai segera setelah dimuat. Oleh karena itu kami melakukan panggilan RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME.

Langkah 3 - Pembuatan konteks OpenGL / manajemen negara
'Craft' menggunakan beberapa pustaka utilitas OpenGL lintas platform untuk berfungsi. Salah satunya dikenal sebagai ‘glew’ (Perpanjangan Perpanjangan Perpustakaan OpenGL), yang lain disebut ‘GLFW’.

Untuk inti GL libretro, kami menggunakan beberapa pustaka internal yang dapat berfungsi sebagai pengganti untuk ini. Untuk port ini kita akan menggunakan dua: glsym (setara dengan glew), dan glsm (mesin negara OpenGL).

Kami ingin port ini berfungsi baik untuk desktop OpenGL (2.0+) dan OpenGL ES seluler (2.0 dan lebih tinggi). Kemudian Anda akan melihat bahwa kita harus mengganti beberapa fungsi seperti 'glGetIntegerv ’di dalam kode sumber untuk memenuhi kriteria ini. Untuk saat ini selama langkah ini kita akan fokus hanya pada mengintegrasikan glsm / glsym dan menyiapkan konteks GL yang bekerja.

Kami akan menambahkan file-file berikut ke proyek:
- deps / libretro-common / glsm / glsm.c
- deps / libretro-common / glsym / rglgen.c
- deps / libretro-common / glsym / glsym_gl.c (untuk desktop GL)
- deps / libretro-common / glsym / glsym_es2.c (untuk ponsel GL)

Untuk menggunakan mesin GL state, Anda terlebih dahulu men-setup konteks GL state machine di dalam fungsi retro_load_game. Anda dapat melihat ini dilakukan di sini:

https://github.com/libretro/Craft/commit/66125d0beee0ad841e53ef2ed86036bced617e4c#diff-7a88199b5738262c9fda4a6bf68eb68cL163

Beberapa catatan pada parameter kedua yang kami berikan kepada glsm_ctl:

context_reset - callback fungsi ini dipanggil setelah konteks GL telah diinisialisasi. Biasanya Anda harus mencoba membersihkan sendiri di sini, (kembali) menginisialisasi grafik, mengatur ulang keadaan tekstur, dll.

context_destroy - callback fungsi ini dipanggil setelah konteks GL dihancurkan. Biasanya Anda akan menghancurkan objek yang dialokasikan di sini terkait dengan GL atau negara lain.

stensil - atur ini ke true jika Anda memerlukan buffer stensil.

Implementasi callback context_reset memerlukan beberapa penjelasan lebih lanjut -

setelah kita tahu bahwa konteks GL telah berhasil dibuat oleh frontend, kita kemudian perlu memberi tahu mesin GL state untuk mengatur ulang konteksnya dan untuk mengatur semua nilai default untuk mesin negara. Kita dapat melakukan ini dengan melakukan panggilan fungsi berikut:

https://github.com/libretro/Craft/commit/66125d0beee0ad841e53ef2ed86036bced617e4c#diff-7a88199b5738262c9fda4a6bf68eb68cR33

Ini mengakhiri bagian setup glsm terkait konteks. Dari sana, cara Anda menggunakannya untuk hanya memanggil ini di awal setiap panggilan retro_run -

https://github.com/libretro/Craft/commit/66125d0beee0ad841e53ef2ed86036bced617e4c#diff-7a88199b5738262c9fda4a6bf68eb68cR167

dan lepaskan lagi keadaan di akhir panggilan fungsi yang sama, seperti ini -

https://github.com/libretro/Craft/commit/66125d0beee0ad841e53ef2ed86036bced617e4c#diff-7a88199b5738262c9fda4a6bf68eb68cR171

Langkah 4 - Reimplementing runloop
Aliran kontrol program reguler biasanya dimulai pada fungsi ‘utama’. ‘Craft’ tidak berbeda. Fungsi ini didefinisikan di dalam file main.c. Dari sana, ia membentuk loop sementara tak terbatas yang berjalan selama permainan terus berjalan. Setelah kita keluar dari game, akhirnya akan keluar dari fungsi yang mengembalikan nilai, menandai keluarnya program.

Untuk mengonversi program seperti 'Kerajinan' ke API libretro, kita perlu melakukan beberapa modifikasi sehingga siklus hidup aplikasi libretro diterapkan dengan benar. Kita akan membahas beberapa fungsi yang diperlukan untuk diterapkan, dan apa yang harus diterapkan di dalam fungsi callback ini.

Untuk membuat Craft berfungsi sebagai inti libretro, kita harus menulis ulang seluruh file main.c dan secara spesifik fungsi main (). Alih-alih satu fungsi besar yang panjang, kami harus membuat beberapa fungsi yang akan dipanggil dari callback fungsi libretro kami:

- void main_init (void);
- kekosongan main_deinit (void);
- void main_load_game (int argc, char * argv);
- void main_unload_game (void);
- void main_run (void);

- retro_init

Ini adalah titik awal utama dari sebuah inti libretro. Anda dapat menginisialisasi sumber daya di sini yang diperlukan agar program dapat berjalan.

Kami akan memanggil 'main_init' dari fungsi ini.
- retro_load_game

Ini adalah fungsi yang dipanggil oleh libretro frontend ketika frontend meneruskan konten ke inti dan inti perlu melakukan sesuatu dengannya. Fungsi retro_load_game selalu dipanggil tidak masalah jika kita memulai inti dengan konten atau tidak.

Dalam kasus ‘Kerajinan’, kami tidak mengharuskan konten apa pun dimuat agar program berjalan. Oleh karena itu, kami dapat mengabaikan sebagian besar parameter 'info' yang diteruskan ke fungsi ini.

Karena ‘Craft’ adalah inti GL libretro, kita harus menyadari sesuatu: Anda dapat melihat bahwa kita kembali lebih awal dalam fungsi ini. Apa yang akan terjadi kemudian adalah bahwa penciptaan konteks GL diatur di belakang layar. Setelah konteks GL siap digunakan, fungsi callback ‘context_reset’ dipanggil. Setelah ini terjadi, kita tahu bahwa konteks GL kami siap untuk digunakan oleh intinya.

Inilah mengapa kami menunda eksekusi 'main_load_game' daripada hanya memanggilnya di dalam fungsi ini. Sebagai gantinya, kita akan memanggil ‘main_load_game’ dari retro_run ketika kita tahu bahwa konteks GL sudah siap.

- retro_run

Ini adalah inti libretro yang setara dengan loop tak hingga, dengan pengecualian bahwa retro_run seharusnya merepresentasikan satu frame video yang layak dieksekusi. Secara default, kami berasumsi bahwa waktu frame akan sama dengan apa yang Anda butuhkan untuk 60 frame per detik gameplay, meskipun mungkin untuk mengkonfigurasi waktu frame pada basis per-retro_run dengan libretro juga. Inti ini tidak mengharuskan kita untuk bermain-main dengan ini, jadi kita mengabaikan aspek ini untuk saat ini.

Dalam inti libretro, diasumsikan bahwa Anda perlu memanggil callback video_cb setidaknya sekali untuk setiap iterasi retro_run, sama dengan panggilan audio. Karena "Kerajinan" tidak memiliki kode audio apa pun, kami tidak akan repot dengan ini.

Seperti yang kami sebutkan sebelumnya selama penjelasan kami tentang 'retro_load_game', inisialisasi konteks perangkat keras GL mungkin memerlukan beberapa waktu hingga siap. Sampai saat itu, kita tidak dapat menggunakan fungsi GL apa pun. Setelah siap, callback ‘context_reset’ akan menetapkan variabel statis ‘init_program_now’ menjadi true. Kami memeriksa ini di dalam retro_run:

if (init_program_now)
{
main_load_game (0, NULL);
init_program_now = false;
video_cb (NULL, game_width, game_height, 0);
kembali;
}

Seperti yang Anda lihat, kami memanggil ‘main_load_game’ pada titik ini untuk akhirnya menginisialisasi game. Anda juga akan melihat bahwa kami menetapkan variabel init_program_now ke false, sehingga fungsi ini tidak lagi dipicu. Kami kemudian melakukan pengembalian awal dari fungsi dan memancarkan bingkai yang ditipu. Kami sekarang siap untuk memainkan game dalam iterasi retro_run berikutnya.

Pada titik ini, alur eksekusi utama dalam panggilan retro_run berikutnya adalah sebagai berikut:

- mengikat mesin GL state

glsm_ctl (GLSM_CTL_STATE_BIND, NULL);

- input jajak pendapat

input_poll_cb ();

- proses input opsional

- panggil main_run sehingga kami mengulangi inti Craft untuk satu frame.

if (main_run ()! = 1)
{}

- lepaskan mesin GL state

glsm_ctl (GLSM_CTL_STATE_UNBIND, NULL);

- render ke layar

video_cb (RETRO_HW_FRAME_BUFFER_VALID, game_width, game_height, 0);

- retro_unload_game

Ini akan memanggil fungsi ini setelah mematikan inti. Di sini, kami deinitialize / gratis
sumber daya apa pun yang terkait langsung dengan konten ‘game’ yang telah kami muat.

Untuk ‘Craft’, konten game sebenarnya tidak dimuat karena intinya tidak
membutuhkan konten eksternal agar dapat berjalan.

Kami akan memanggil main_unload_game dari fungsi ini.

- retro_deinit

Fungsi ini dipanggil setelah ‘retro_unload_game’. Di sini, kami akan menonaktifkan semua
sumber daya lain yang terkait dengan inti itu sendiri yang belum di-inisiasi selama
‘Retro_unload_game’.

Kami akan memanggil 'main_deinit' dari fungsi ini.

Langkah 5 - Memanggang aset

'Craft' asli akan mengkompilasi shader dari file sumber yang disimpan di dalam subdirektori, dan juga akan mencari teksturnya di dalam subdirektori.

Karena para shader ini cukup banyak dibutuhkan untuk program bekerja dan karena teksturnya relatif kecil, kami membuat keputusan untuk memanggang aset-aset ini ke dalam kode utama. Dengan begitu, kami tidak akan membebani pengguna dengan harus menyimpan aset-aset ini di suatu tempat di mana inti libretro dapat menemukan dan menggunakannya. Kami juga nantinya dapat membuat perubahan pada mereka lebih mudah untuk tujuan kompatibilitas OpenGL ES.

Untuk mengkonversi file PNG, kita akan menggunakan program yang disebut bin2c (yang dapat ditemukan di Github), dan melakukan perintah berikut:

tekstur bin2c / font.png tekstur / font_texture.h font_texture

tekstur bin2c / sign.png tekstur / sign_texture.h sign_texture

tekstur bin2c / tekstur sky.png / sky_texture.h sky_texture

tekstur bin2c / texture.png tekstur / tiles_texture.h tiles_texture

Kami sekarang menyertakan header ini di dalam file src / main.c.

Craft menggunakan alat middleware yang disebut 'lodepng' untuk memuat dan men-decode file PNG ke dalam memori. Kode asli akan menggunakan fungsi pemuatan I / O file lodepng untuk memuat file PNG. Karena kita akan menggunakan file PNG dari memori, kita perlu menggunakan fungsi yang berbeda yang disediakan oleh lodepng: lodepng_decode32. Ini akan memungkinkan kita untuk mengarahkannya ke buffer memori sumber (file PNG dalam memori yang diubah) dan kemudian membuangnya output yang didekodekan ke buffer memori tujuan, yang kemudian dapat kita berikan ke OpenGL.Baca juga: map raport
5 24
Copyright © 2015. OKEbutik Template Allright reserved.