Bagian Dalam Game Retro: Punch-Out untuk NES

gambar

Bagian 1. Kata Sandi


Permainan NES Mike Tyson Punch-Out menggunakan sistem kata sandi yang memungkinkan pemain untuk melanjutkan permainan dari titik tertentu. Setiap kata sandi terdiri dari 10 digit, yang dapat berkisar dari 0 hingga 9. Permainan dapat menerima dua jenis kata sandi, yang saya sebut kata sandi "normal" dan "khusus". Kata sandi khusus adalah kombinasi tertentu dengan 10 digit, input yang gimnya bereaksi dengan cara yang unik. Daftar lengkap kata sandi khusus terlihat seperti ini:

  • 075 541 6113 - sinyal sibuk 1
  • 800 422 2602 - sinyal sibuk 2
  • 206 882 2040 - sinyal sibuk 3
  • 135 792 4680 - permainan di turnamen tersembunyi: "Sirkuit Dunia Lain" (agar kata sandi dapat diterima, Anda harus menahan tombol Pilih dan tekan A + B)
  • 106 113 0120 - tampilan judul (agar kata sandi dapat diterima, Anda harus menahan tombol Pilih dan tekan A + B)
  • 007 373 5963 - mentransfer pemain ke pertempuran dengan Mike Tyson

Jenis kata sandi kedua yang diterima oleh game adalah kata sandi biasa. Dalam kata sandi reguler, progres yang dibuat pemain dalam game disandikan. Data permainan berikut ini disandikan dalam kata sandi biasa:

  • Jumlah karier yang menang
  • Jumlah kerugian karier
  • Knockout menang
  • Lawan berikutnya

Pengodean Kata Sandi


Sebagai contoh, untuk mempelajari pembuatan kata sandi, kami menggunakan game dengan 24 kemenangan, 1 kerugian, 19 KO dan dimulai di turnamen dunia dengan pertempuran melawan Manusia Super Macho.

Proses penyandian status permainan dalam kata sandi dimulai dengan mengumpulkan jumlah kemenangan, kekalahan dan KO ke dalam buffer. Gim ini menyajikan setiap angka dalam bentuk kode desimal biner yang terdiri dari 8 bit per digit dan 2 digit untuk setiap nilai. Artinya, untuk 24 kemenangan, Anda memerlukan satu byte dengan nilai 2 dan byte kedua dengan nilai 4. Hal yang sama terjadi dengan pasangan byte untuk kerugian dan KO, yaitu total 6 byte data diperoleh. Dalam diagram di bawah ini, 6 byte ini ditandai dengan nilai dalam desimal dan biner.


Langkah selanjutnya adalah membuat checksum untuk 6 byte ini. Byte checksum dihitung dengan menambahkan 6 byte terpisah dan mengurangi hasil dari 255. Dalam kasus kami, 2 + 4 + 0 + 1 + 1 + 9 = 17, yaitu, 255 - 17 = 238.

Kemudian kita menulis beberapa bit 6 byte ke buffer baru. Buffer ini dapat diartikan sebagai satu nilai menengah 28-bit, yang akan kami isi selangkah demi selangkah. Bit dari buffer pertama dibagi menjadi kelompok dua dan dipindahkan ke posisi hard-code buffer kedua yang berbeda. Ini adalah yang pertama dari beberapa langkah yang tugasnya hanya mengaburkan data untuk mempersulit proses menghasilkan kata sandi untuk pemain.


Perhatikan bahwa tidak semua bit dari buffer asli ditransfer ke buffer perantara baru. Bit-bit ini diabaikan, karena diketahui bahwa mereka selalu 0. Berkat aturan permainan, sudah cukup untuk mengirimkan jumlah kerugian dalam kata sandi dengan hanya 2 bit informasi. Jika jumlah total kerugian mencapai 3, maka game over terjadi dan pemain tidak menerima kata sandi. Oleh karena itu, cukup menggambarkan jumlah kerugian dengan angka 0, 1 dan 2, dan untuk ini hanya 2 bit yang cukup.

Kemudian kita menulis pasangan bit lain ke buffer perantara. Empat pasangan pertama diambil dari nilai checksum yang dihitung sebelumnya. Sepasang lainnya diambil dari nilai musuh. Nilai musuh adalah angka yang menunjukkan musuh mana yang akan dilawan pemain setelah memasukkan kata sandi. Tiga kemungkinan nilai musuh dapat digunakan:

0 - DON FLAMENCO (pertarungan pertama turnamen utama)

1 - PISTON HONDA (pertarungan pertama turnamen dunia)

2 - SUPER MACHO MAN (pertarungan terakhir turnamen dunia)

Karena kami ingin membuat kata sandi yang berhadapan dengan Super Macho Man, kami menggunakan 2 sebagai nilai musuh.Kemudian, bit checksum dan nilai-nilai musuh ditulis ke dalam bit menengah sebagai berikut:


Langkah selanjutnya adalah melakukan beberapa permutasi siklik dari bit antara ke kiri. Satu permutasi siklik ke kiri berarti semua bit digeser satu posisi ke kiri, dan bit yang paling kiri bergerak dan menjadi yang paling kanan. Untuk menghitung jumlah permutasi ke kiri, kami mengambil jumlah dari nilai lawan dan jumlah kerugian, menambah 1 dan mengambil sisa pembagian dengan 3 hasil ini. Dalam kasus kami, ternyata 2 + 1 + 1 = 4. Kemudian sisanya dari 4/3 adalah 1, jadi kami secara siklus menggeser bit antara ke kiri satu kali.


Pada titik ini, bit perantara sudah tercampur secara menyeluruh dan inilah saatnya untuk mulai memecahnya untuk mendapatkan angka yang membentuk kata sandi. Kata sandi harus terdiri dari 10 digit, jadi kami akan memecah 28 bit menengah menjadi 10 angka terpisah, yang akan kami sebut nilai kata sandi P0, P1, P2, dll. Masing-masing dari sembilan nilai kata sandi pertama menerima 3 bit data, dan yang terakhir hanya mendapatkan satu bit antara. Untuk menyelesaikan nilai kata sandi yang telah selesai, kami juga akan menyertakan bit yang menunjukkan jumlah permutasi yang dilakukan pada langkah sebelumnya.


Akhirnya, kami menambahkan ke masing-masing nilai kata sandi offset unik dan kode keras. Digit kata sandi yang telah selesai akan menjadi sisa jumlah ini dari pembagian dengan 10. Misalnya, pada posisi ketujuh kita menggunakan offset 1, yaitu, kita mendapatkan 5 + 1 = 6, dan digit terakhir adalah sisa dari 6/10, yaitu 6. Pada posisi keempat yang kita gunakan offset 7, yaitu, kita mendapatkan 5 + 7 = 12, dan angka terakhir sama dengan sisanya 12/10, yaitu 2.


Jadi, kami mendapat digit kata sandi siap pakai yang dapat diperiksa di dalam game.


Penguraian kata sandi


Proses decoding kata sandi kembali ke jumlah menang / kalah / KO dan nilai lawan adalah implementasi sederhana dalam urutan terbalik dari semua langkah yang dijelaskan di atas. Saya akan meninggalkannya sebagai tugas bagi pembaca. Namun, gim ini memiliki dua kesalahan penting yang terjadi saat mendekode dan memeriksa kata sandi yang dimasukkan oleh pemain.

Kesalahan pertama terjadi pada langkah pertama decoding kata sandi, yaitu ketika mengurangi offset untuk kembali ke nilai kata sandi. Nilai kata sandi awal masing-masing berisi 3 bit data, yaitu nilainya sebelum menerapkan offset harus dalam kisaran 0-7. Namun, pemain dapat memasukkan kata sandi, yang setelah dikurangi dengan offset menghasilkan nilai kata sandi 8 atau 9 (dibagi 10 dengan sisanya). Alih-alih segera menolak kata sandi seperti itu, gim secara keliru tidak memverifikasi kasus ini dan memungkinkan Anda untuk menambahkan bit data tambahan ke nilai kata sandi yang dapat mencemari himpunan bit antara sedemikian rupa sehingga kata sandi tidak lagi unik. Karena bit perantara tertentu dapat diatur baik dengan digit kata sandi yang sesuai, ATAU dengan bit tambahan dari nilai kata sandi tetangga, ada banyak kata sandi yang dapat dikonversi ke rangkaian bit perantara yang sama. Itulah sebabnya Anda dapat menemukan kata sandi berbeda yang memberikan hasil dalam gim yang sama, meskipun seharusnya unik.

Kesalahan kedua adalah bug dalam logika yang digunakan game untuk memverifikasi data setelah menguraikan sandi. Game ini mencoba menerapkan kondisi berikut:

  • checksum yang disimpan dalam kata sandi sesuai dengan checksum yang harus diperoleh dengan mempertimbangkan jumlah kemenangan / kerugian / KO yang tersimpan dalam kata sandi
  • nilai kerugian adalah 0, 1 atau 2
  • nilai musuh adalah 0, 1 atau 2
  • jumlah permutasi siklik yang disimpan dalam kata sandi adalah angka yang benar dengan mempertimbangkan nilai kerugian dan nilai lawan yang disimpan dalam kata sandi
  • semua nomor win / loss / knockout yang tersimpan dalam kata sandi berada dalam kisaran 0-9
  • menang> = 3
  • menang> = KO

Jika salah satu dari kondisi ini tidak terpenuhi, maka permainan harus menolak kata sandi. Namun, ada bug dalam pelaksanaan pemeriksaan akhir (yaitu, ketika memeriksa angka yang dikodekan oleh BCD.) Alih-alih memeriksa kemenangan> = KO, permainan memungkinkan kasus di mana jumlah kemenangan atas adalah 0, jumlah kemenangan yang lebih rendah> = 3, dan jumlah yang lebih tinggi dari KO kurang dari jumlah yang lebih rendah menang. Misalnya, rekor dengan 3 kemenangan, 0 kekalahan dan 23 KO akan diterima oleh permainan (yang membuktikan kata sandi 099 837 5823), meskipun harus ditolak (karena tidak mungkin memenangkan 23 pertarungan dengan KO jika Anda menang hanya dalam 3 pertarungan.)

Kesimpulan


Detail khusus dari skema pengkodean seperti ini adalah unik untuk Punch-Out, tetapi gagasan umum untuk mendapatkan bit penting dari kondisi permainan, mengonversinya dengan kemungkinan restorasi untuk mengaburkan keadaan awal, dan kemudian menggunakannya untuk menghasilkan sejumlah karakter tertentu untuk diperlihatkan kepada pemain sebagai kata sandi merupakan pendekatan yang cukup universal. Anda dapat menggunakan checksum sehingga perubahan kata sandi yang tidak disengaja (misalnya, jika pemain membuat kesalahan) paling sering menyebabkan penolakannya, daripada membuat kata sandi lain dengan keadaan permainan acak.

Bagian 2. Tinjauan Punch-Out


Setiap petarung di Punch-Out Mike Tyson !!! dikontrol oleh satu atau lebih skrip bytecode yang ditafsirkan. Karakter pemain, Little Mac, menjalankan skrip sederhana yang berisi logika dari setiap aksi yang tersedia untuk pemain (penghindaran, blok, pukulan, dll.) Karakter lawan dikontrol oleh 3 level skrip independen yang bersama-sama menciptakan perilaku karakter.


Skrip pencocokan


Skrip musuh tingkat tertinggi dieksekusi di seluruh 3 putaran pertempuran dan mengendalikan perubahan paling ambisius dalam perilaku lawan. Saya akan menyebut skrip ini "skrip pencocokan". Tugas utamanya adalah memilih perilaku yang akan dilakukan musuh dalam menanggapi berbagai peristiwa selama pertempuran. Misalnya, perilaku tertentu akan langsung dipicu setelah lawan bangkit setelah knockdown, atau ketika pemain kehabisan hati dan menjadi lelah. Perilaku ini ditulis di atas meja dan dipanggil oleh mesin permainan dalam menanggapi peristiwa yang sesuai. Skrip pertandingan juga menetapkan nilai awal untuk opsi konfigurasi yang terkait dengan kompleksitas pertempuran (misalnya, jumlah waktu yang lawan tetap rentan setelah serangan terjawab.) Akhirnya, skrip pertandingan mulai menunggu penanda sementara tertentu selama pertempuran untuk membuat perubahan pada nilai yang ditetapkan sebelumnya. .

Script perilaku


Skrip lawan dari tingkat yang lebih rendah adalah "skrip perilaku". Level ini bertanggung jawab atas urutan pukulan dan serangan tertentu yang harus dilakukan lawan dalam kerangka perilaku saat ini (ditetapkan oleh skrip pertandingan.) Skrip perilaku mengeksekusi perintah seperti "menerapkan jab kanan, jeda selama 28 frame, secara acak menerapkan pukulan kiri atau kanan, ulangi semua ini 5 kali. " Skrip juga memiliki perintah untuk membaca dan menulis ke alamat apa pun di memori dari mesin game, sehingga perilakunya bisa sangat dinamis.

Script animasi


Skrip musuh level terendah adalah "skrip animasi". Skrip tersebut melakukan perincian setiap serangan, blok, atau serangan khusus sebagai bagian dari perilaku (ditentukan oleh skrip perilaku). Pada level ini, perintah seperti "tetapkan sprite 23 ke bingkai animasi musuh saat ini, gerakkan ke bawah dan ke kanan sebesar 1 piksel setiap frame kedua dalam untuk 10 frame berikutnya, ubah frame animasi menjadi sprite 24, mainkan efek suara 7 ". Selain perintah animasi, skrip animasi juga melakukan urutan berbagai perubahan dalam status gameplay yang terkait erat dengan gerakan musuh. Misalnya, dalam animasi panjang serangan khusus, skrip animasi dapat menyisipkan perintah yang membuat musuh rentan terhadap knockdown dengan satu pukulan dalam periode waktu yang sangat singkat. Seperti halnya skrip perilaku, skrip animasi dapat membaca dan menulis alamat memori sewenang-wenang dalam mesin game untuk mencapai efek yang lebih dinamis.

Script Little Mac


Script yang dieksekusi oleh karakter Little Mac player paling mirip dengan skrip animasi musuh. Ini mengubah bingkai saat ini dari animasi yang dipantulkan dan menggerakkan pemain di sekitar layar. Seperti skrip animasi, skrip Little Mac mengeksekusi urutan peristiwa gameplay tertentu, misalnya, pada titik waktu tertentu Mac akan mengenai musuh, atau kapan harus mengeksekusi blok atau penghindaran. Skrip Little Mac mengontrol input pemain, mirip dengan bagaimana skrip perilaku mengontrol skrip animasi musuh.

Masing-masing dari empat skrip ini diproses oleh penerjemahnya sendiri. Meskipun banyak dari mereka memiliki fungsi yang sama, misalnya, kontrol kontrol dasar dan akses langsung ke memori, setiap sistem mengimplementasikan versinya sendiri, dan tidak berbagi kode umum (atau ruang opcode) dengan sistem lain. Ini memungkinkan setiap jenis skrip untuk menjadi sangat spesifik dan efektif menggunakan satu set kecil perintah target. Data skrip membentuk sekitar 22% dari data non-grafis dari gim permainan (kode mesin untuk gim itu sendiri hanya memakan 17%), jadi sangat penting bahwa skrip memiliki tampilan yang ringkas.

Bagian 3. Script Pencocokan Punch-Out


Skrip pertandingan mengontrol perilaku lawan di level tertinggi. Operasi utama yang ia lakukan berulang kali adalah menunggu waktu putaran tertentu dan membuat perubahan pada data konfigurasi lawan pada saat itu. Video menunjukkan putaran pertama pertempuran pertama melawan Bald Bull, bersama dengan skrip pertandingan yang mengontrol perilaku keseluruhannya.


Ada tiga operasi utama yang dapat dilakukan skrip pertandingan. Yang pertama adalah menunggu sampai pengatur waktu mencapai nilai tertentu. Yang kedua adalah menanyakan apakah perilaku musuh saat ini telah berubah. Perilaku dicatat dalam tabel konfigurasi pertempuran di memori, dan kemudian dipanggil pada waktu yang berbeda oleh skrip pertandingan dan mesin game itu sendiri. Tabel ini memiliki dua segmen perilaku yang digunakan oleh skrip pertandingan. Saya menyebutnya perilaku "dasar" dan perilaku "khusus". Perilaku khusus, misalnya, serangan Muatan Banteng dari lawan Bald Bull atau Honda Rush dari lawan Piston Honda, dan perilaku utama adalah pukulan biasa yang diberikan lawan selama sisa waktu. Skrip perilaku khusus yang digunakan untuk menerapkan tipe perilaku ini dapat diubah oleh skrip pertandingan langsung selama pertempuran, sehingga pejuang dapat memulai dengan satu perilaku utama dan kemudian beralih ke perilaku lainnya (seperti yang terlihat dalam video, Bald Bull melakukan ini ketika timer mencapai 0 : 20.)

Fitur perubahan perilaku yang dilakukan oleh skrip pertandingan adalah bahwa mereka dapat digantikan oleh perubahan perilaku yang diminta oleh mesin game. Mesin permainan menggunakan empat segmen perilaku untuk meminta perilaku baru ketika Mac kehilangan semua hatinya dan menjadi lelah, dan juga ketika lawan bangkit setelah knockdown. Jika skrip pertandingan memenuhi permintaan untuk mengubah perilaku, tetapi salah satu dari empat peristiwa mesin game ini terjadi sebelum permintaan diproses (permintaan tidak dapat diproses sampai lawan memasuki kondisi tunggu), maka mesin permainan menetapkan perilaku yang diinginkan dan permintaan untuk skrip pertandingan ditolak. Beberapa pejuang, seperti Bald Bull, meminta perilaku khusus beberapa kali selama periode waktu yang singkat. Tampaknya ini hanya diperlukan untuk mengurangi kemungkinan bahwa salah satu permintaan ini akan dibatalkan secara tidak sengaja.

Operasi utama ketiga dari skrip pertandingan adalah penambalan memori. Sebagian besar tambalan memori memengaruhi tabel konfigurasi pertempuran, tempat skrip perilaku direkam. Selain serangkaian perilaku, tabel berisi data yang terkait dengan kompleksitas pertempuran. Misalnya, ketika timer di video mencapai 0:30, Bald Bull mengubah pengaturan keamanannya. Ini mengarah pada fakta bahwa pemain tidak bisa lagi menipu dia dengan menekan, dan kemudian melakukan pukulan ke tubuh. Selain itu, skrip pertandingan memiliki kemampuan untuk menambal alamat memori sewenang-wenang, tetapi fungsi ini hanya digunakan sekali - pada awal babak kedua dengan Mike Tyson, sehingga pemain menerima bintang untuk pertama kalinya ketika ia memukulnya, yang berada dalam mode siaga.

Bagian 4. Skrip Perilaku Punch-Out


Sekarang kita melihat skrip perilaku yang terlibat langsung dalam menerapkan perilaku.

Video tersebut menunjukkan interpretasi tentang bagaimana skrip perilaku saingan Piston Honda 1 mungkin terlihat dalam tim Inggris.


Perintah Animasi


Skrip perilaku bertanggung jawab untuk meluncurkan animasi secara berurutan dengan cara yang sama seperti skrip pertandingan bertanggung jawab untuk meluncurkan animasi. Perintah anim memainkan animasi tertentu, dan perintah anim_rnd melakukan animasi yang dipilih secara acak dari daftar 8 opsi. Dalam video di atas, pada saat pemilihan acak dari daftar opsi, opsi yang dipilih sebentar disorot dalam warna merah. Ketika Piston Honda menerapkan dua pukulan pertama, anim digunakan untuk masing-masingnya. Setelah itu, ia menggunakan anim_rnd untuk secara acak memilih dari set yang berisi 6 animasi kait dan 2 animasi kosong. Sebagai akibatnya, ia mengait pada 75% dari waktu, dan tidak melakukan apa-apa pada 25% dari waktu.

Dari sudut pandang skrip, perilaku animasi dimainkan secara serempak, karena ketika sistem animasi tidak dalam mode siaga, penerjemah skrip akan dijeda.

Perintah kontrol eksekusi


Ada beberapa perintah yang mengubah pelaksanaan skrip perilaku itu sendiri. Perintah jeda dapat menghentikan sementara eksekusi skrip untuk sejumlah bingkai tertentu, atau untuk sejumlah bingkai yang dipilih secara acak dari daftar 2 opsi.

Ada berbagai perintah percabangan yang, dalam kondisi tertentu, secara opsional beralih ke bagian skrip perilaku yang berbeda. branch_rnd memiliki probabilitas tertentu bahwa cabang akan muncul setiap kali dieksekusi. Kasus khusus percabangan probabilistik adalah perintah branch_always , yang memiliki 100% kemungkinan percabangan.

Mekanisme loop sederhana dibangun ke dalam interpreter script perilaku. Perintah set_loop_count menetapkan nilai saat ini dari penghitung lingkaran. Setiap kali perintah branch_while_loop ia mengurangi nilai penghitung loop oleh satu dan melakukan percabangan hanya jika nilai penghitung lebih besar dari nol.

Jenis percabangan terakhir memeriksa isi memori untuk membuat keputusan tentang percabangan. Piston Honda menggunakan perintah branch_mem_test ini untuk memeriksa apakah serangan terakhirnya dalam perilaku tertentu berhasil. Jika hit mencapai target, maka itu bercabang untuk hit berikutnya. Jika hit tidak berhasil, maka itu menggunakan perintah branch_while_loop untuk terus menekan hanya ketika 5 hit gagal menumpuk.

Perintah Perilaku


Ada dua perintah di mana skrip perilaku dapat mengontrol sistem perilaku itu sendiri. Perintah begin_behavior_main digunakan untuk mengakhiri perilaku yang dapat dieksekusi saat ini dan memulai perilaku utama. Ini berbeda dengan percabangan dalam skrip perilaku, karena bagian skrip yang dianggap sebagai perilaku "utama" saat ini dapat diubah selama pertandingan dengan skrip pertandingan (lihat bagian sebelumnya dari artikel tentang skrip pertandingan).

Perintah lain yang berhubungan dengan perilaku adalah enable_behavior_change . Ketika perilaku baru diluncurkan, itu dimulai dengan keadaan kunci, ketika semua permintaan lebih lanjut untuk mengubah perilaku diblokir. Menggunakan perintah enable_behavior_change skrip memberi sinyal bahwa ia siap untuk mengizinkan perilaku lain. Misalnya, dalam perilaku khusus Piston Honda, perintah enable_behavior_change tidak pernah dieksekusi, jadi jika Mac lelah selama waktu ini, maka perilaku khusus berlanjut. Namun, peristiwa knockdown mem-bypass sistem ini, jadi jika selama perilaku khusus Piston Honda, karakter utama dirobohkan, perilaku tersebut akan berubah.

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


All Articles