
Posting ini adalah pengantar untuk konsol video konsol "buatan sendiri" proyek saya yang dibuat dari awal. Saya terinspirasi oleh konsol retro dan sampel modern, tapi saya punya arsitektur sendiri. Teman-teman saya terus-menerus mengatakan kepada saya bahwa saya harus berbicara tentang proyek saya, dan tidak melakukan semuanya secara eksklusif "untuk diri saya", jadi di sini saya menerbitkan posting ini.
Perhatian, ini adalah terjemahan
Bagaimana semuanya dimulai
Nama saya Sergio Vieira, saya dibesarkan di Portugal pada tahun 80-an dan 90-an, saya memiliki nostalgia panjang untuk game retro, terutama untuk konsol generasi ketiga dan keempat.
Beberapa tahun yang lalu, saya memutuskan untuk lebih memahami elektronik dan mencoba membuat awalan saya sendiri.
Secara profesi, saya seorang programmer dan tidak memiliki pengalaman sebagai insinyur elektronik, kecuali untuk (dan tidak boleh dianggap) upgrade independen destkop saya.
Meskipun saya tidak memiliki pengalaman, saya berkata pada diri sendiri βmengapa tidak?β, Saya membeli beberapa buku, beberapa peralatan elektronik dan mulai belajar berdasarkan perasaan saya tentang apa yang layak dipelajari.
Saya ingin membuat awalan yang mirip dengan yang menyebabkan saya merasa nostalgia, saya ingin sesuatu antara NES dan Super Nintendo , atau mungkin antara Sega Master System dan Mega Drive .
Konsol ini memiliki CPU, chip video asli (mereka tidak disebut GPU saat itu) dan chip audio, kadang-kadang built-in, dan kadang-kadang eksternal.
Gim-gim tersebut didistribusikan pada kartrid, yang pada umumnya adalah perpanjangan dari besi, kadang-kadang hanya chip ROM, dan kadang-kadang memiliki komponen tambahan.
Rencana awal adalah membuat awalan dengan karakteristik berikut:
- Tanpa emulasi, permainan dan program harus bekerja pada perangkat keras nyata, tidak harus sama dengan waktu itu, tetapi cukup cepat untuk tugas itu, dan tidak lebih.
- Dengan CPU retro nyata.
- Dengan output TV analog.
- Dengan suara
- Dengan dukungan pengontrol ganda
- Menggulir becks dan animasi sprite
- Dengan fitur untuk mendukung game platform seperti Mario, dan tentu saja segala macam game lainnya.
- Dengan mengunduh game dan program dari kartu SD.
Mengapa kartu SD, dan bukan kartrid, well, pada dasarnya itu jauh lebih praktis, Anda dapat menyalinnya dari komputer Anda. Dan kartrid berarti, pertama, lebih banyak zat besi di kotak set-top, dan kedua, untuk menghasilkan zat besi untuk setiap program.
Produksi
Sinyal video
Hal pertama yang saya lakukan adalah menghasilkan sinyal video.
Setiap konsol dari periode yang saya ambil sebagai sampel memiliki berbagai chip grafis berpemilik, yang berarti bahwa mereka semua memiliki spesifikasi yang berbeda.
Untuk alasan ini, saya tidak ingin menggunakan chip grafis yang sudah jadi, saya ingin konsol saya memiliki spesifikasi grafis yang unik. Dan karena saya tidak dapat membuat chip grafis saya sendiri, dan pada saat itu saya masih tidak dapat menggunakan FPGA, saya memutuskan untuk membatasi diri pada generasi yang dihasilkan oleh perangkat lunak dari sinyal grafis menggunakan mikrokontroler 8-bit, 20 megahertz.
Ini tidak terlalu banyak, dan hanya solusi yang cukup kuat untuk grafik tingkat yang saya tertarik.
Jadi, saya mulai menggunakan mikrokontroler Atmega644 pada kemurnian 20 MHz untuk menghasilkan sinyal video PAL untuk TV. Saya harus bit-beat protokol PAL karena chip itu sendiri tidak tahu bagaimana cara melakukannya.


Mikrokontroler menghasilkan warna 8-bit (RGB332, 3 bit merah, 3 bit hijau dan 2 biru) dan DAC pasif mengubah semuanya menjadi RGB. Untungnya di Portugal, hampir semua TV dilengkapi dengan konektor SCART dan mereka mendukung input RGB.
Subsistem grafik yang benar
Karena mikrokontroler cukup kuat, dan saya memutuskan untuk menggunakannya secara eksklusif untuk menghasilkan sinyal video (saya menyebutnya VPU - Video Processing Unit), saya memutuskan untuk mengatur buffer ganda pada saat yang sama.
Ternyata mikrokontroler kedua (PPU, Picture Processing Unit, chip Atmega1284 juga pada 20 MHz) menghasilkan gambar dalam chip RAM 1 (saya menyebutnya VRAM1), dan yang pertama mengirim isi chip kedua (VRAM2) ke TV pada saat yang sama.
Setelah satu frame, dan dua frame dalam sistem PAL adalah 1/25 detik, VPU mengganti VRAM dan mereka bertukar, PPU menghasilkan gambar dalam VRAM2, dan VPU membuang VRAM1 ke output TV.
Kartu video ternyata sangat rumit karena saya harus menggunakan perangkat keras eksternal sehingga kedua mikrokontroler dapat menggunakan kedua modul memori dan untuk mempercepat akses ke RAM, karena juga memiliki bit-banging, jadi saya harus menambahkan chip seri 74 sebagai penghitung, pemilih jalur, transceiver, dll. .
Firmware untuk VPU dan PPU juga ternyata tidak praktis karena saya harus menulis banyak kode untuk mendapatkan kecepatan maksimum dari grafik. Pada awalnya semuanya ditulis dalam assembler, kemudian sebagian ditulis ulang dalam C.


Akibatnya, PPU menghasilkan gambar 224x192 piksel, yang kemudian dikirim ke TV melalui VPU. Anda mungkin menemukan resolusi rendah, tetapi sebenarnya hampir sebanyak konsol waktu itu sebenarnya, biasanya 256x224. Resolusi yang sedikit lebih rendah, tetapi memungkinkan saya untuk menambahkan lebih banyak fitur yang dikelola sistem untuk menghitung dalam satu bingkai.
Seperti di masa lalu, PPU memiliki mekanik kaku sendiri yang harus Anda dapat gunakan. Backing (backing) diberikan dari 8x8 karakter piksel, juga disebut ubin. Ternyata ukuran latar belakang adalah 28x24 ubin.
Agar backing dapat menggulir dengan lancar, pixel demi pixel, saya melakukannya sehingga ada 4 layar virtual, masing-masing 28x24 ubin yang masuk dalam memori secara berurutan dan dililit satu sama lain, dalam gambar itu lebih jelas.


Di atas latar belakang, PPU dapat membuat 64 sprite yang dapat 8 atau 16 piksel tinggi atau lebar, yaitu, 1, 2 atau 4 ubin dan juga dapat membalik secara horizontal dan / atau vertikal.
Di atas bagian belakang, Anda juga dapat membuat overlay dengan ukuran satu buffer 28x6 ubin, ini dimaksudkan untuk merender HUD, skor agar tidak mengganggu sprite utama dan pengguliran bagian belakang.
Salah satu fitur "lanjutan" adalah bahwa backing dapat digulir tidak sepenuhnya, tetapi setiap baris secara terpisah, yang memungkinkan segala macam efek menarik seperti layar terbagi atau hampir- paralaks .
Ada juga tabel atribut yang memungkinkan Anda untuk mengatur setiap ubin ke nilai dari 0 hingga 3, dan kemudian Anda bisa menentukan halaman ubin untuk semua ubin dengan satu atribut atau menambah nilai simbolisnya. Ini nyaman ketika ada bagian cadangan yang perlu diubah secara teratur dan CPU tidak harus menghitung setiap ubin secara individual, cukup untuk hanya mengatakan sesuatu seperti: "semua ubin dengan atribut 1, menambah nilai numerik karakter Anda sebesar 2", hal-hal seperti itu dapat diimplementasikan dengan teknik yang berbeda amati, misalnya, di ubin petak di Mario di mana tanda tanya dianimasikan atau di permainan di mana ada air terjun di mana semua ubin terus berubah menciptakan efek air jatuh.
CPU
Ketika kartu video saya berfungsi, saya mulai bekerja dengan CPU sebagai Zilog 80 untuk set-top box saya.
Salah satu alasan mengapa Z80 dipilih, selain fakta bahwa itu adalah CPU retro yang keren, adalah kemampuannya untuk mengatasi dua ruang 16-bit, satu untuk memori dan yang kedua untuk port I / O, tidak kalah legendaris 6502 , misalnya, tidak dapat , itu hanya dapat mengatasi ruang 16 bit, dan Anda harus memetakannya ke dalam memori serta berbagai perangkat eksternal, video, audio, joystick, generator nomor acak perangkat keras, dll. Lebih mudah memiliki dua ruang alamat, satu sepenuhnya diberikan hingga 64 kilobyte kode dan data dalam memori dan yang kedua untuk akses ke perangkat eksternal.
Pertama, saya menghubungkan CPU ke EEPROM di mana program pengujian saya berada dan juga menghubungkannya melalui ruang I / O ke mikrokontroler yang saya instal sehingga saya bisa berkomunikasi dengan komputer saya melalui RS232 dan memantau bagaimana CPU dan segala sesuatu bekerja. Mikrokontroler Atmega324 ini berjalan pada 20 MHz yang saya sebut unit mikrokontroler input / output IO MCU, bertanggung jawab untuk mengontrol akses ke pengendali game (joystick), pembaca kartu SD, keyboard PS / 2 dan komunikator melalui RS232.

CPU terhubung ke chip memori 128 kilobyte, yang mana hanya 56 kilobyte yang tersedia, ini tentu saja tidak masuk akal, tetapi saya hanya bisa mendapatkan 128 atau 32 kilobyte chip. Ternyata memori tersebut terdiri dari 8 kilobyte ROM dan 56 kilobyte RAM.
Setelah itu, saya memperbarui firmware IO MCU menggunakan perpustakaan ini dan saya mendapat dukungan untuk pembaca kartu SD.
Sekarang CPU dapat menelusuri direktori, melihat apa yang ada di dalamnya, membuka dan membaca file. Semua ini dilakukan dengan menulis dan membaca ke alamat tertentu di ruang I / O.
Hubungkan CPU ke PPU
Hal berikutnya yang saya lakukan adalah koneksi antara CPU dan PPU. Untuk melakukan ini, saya menerapkan "solusi sederhana" yaitu membeli dual-port RAM, ini adalah chip RAM yang dapat dihubungkan langsung ke dua bus yang berbeda. Ini memungkinkannya untuk menyingkirkan chip tambahan seperti penyeleksi garis dan, lebih lagi, memungkinkan akses hampir simultan ke memori dari kedua chip. PPU lain dapat langsung mengakses CPU pada setiap frame dengan mengaktifkan interupsi yang tidak bisa ditutup-tutupi . Ternyata CPU menerima interupsi pada setiap frame, yang berguna untuk berbagai tugas pengaturan waktu dan untuk memahami kapan saatnya melakukan pembaruan grafik.
Setiap bingkai interaksi CPU, PPU dan VPU terjadi sesuai dengan skema berikut:
- PPU menyalin informasi dari memori PPU ke memori internal.
- PPU mengirimkan sinyal interupsi ke CPU.
- Pada saat yang sama:
- CPU melompat ke fungsi interupsi dan mulai memperbarui memori PPU dengan kondisi grafis baru. Program harus kembali dari interupsi hingga blok berikutnya.
- PPU membuat gambar berdasarkan informasi yang sebelumnya disalin ke salah satu VRAM.
- VPU mengirimkan gambar dari VRAM lain ke output TV.
Sekitar waktu yang sama, saya mulai mendukung pengontrol permainan, pada awalnya saya ingin menggunakan pengontrol Nintendo, tetapi soket mereka adalah milik dan umumnya sulit ditemukan, jadi saya memilih pengontrol 6 tombol yang kompatibel dengan Mega Drive / Genesis, mereka memiliki soket DB-9 standar yang mana-mana.

Menulis game nyata pertama
Pada saat ini, saya sudah memiliki CPU yang mampu mengendalikan PPU, bekerja dengan joystick, membaca kartu SD ... sudah waktunya untuk menulis game pertama , tentu saja di assembler Z80, saya butuh beberapa hari dari waktu luang.
Tambahkan grafik dinamis
Semuanya super, saya memiliki konsol permainan sendiri, tetapi ini tidak cukup bagi saya, karena dalam permainan saya harus menggunakan grafik yang dijahit dalam memori PPU dan tidak mungkin untuk menggambar ubin untuk permainan tertentu dan itu hanya dapat diubah dengan memencet ROM. Saya mulai berpikir tentang cara menambahkan lebih banyak memori sehingga CPU dapat memuat karakter untuk ubin ke dalamnya, dan kemudian PPU kemudian bisa membaca semuanya dari sana dan bagaimana melakukannya lebih mudah karena awalannya ternyata rumit dan besar.
Dan saya datang dengan yang berikut ini: hanya PPU yang akan memiliki akses ke memori baru ini, dan CPU akan memuat data di sana melalui PPU dan saat proses pemuatan ini sedang berlangsung, memori ini tidak dapat digunakan untuk menggambar, tetapi akan dimungkinkan untuk menggambar dari ROM saat ini.
Setelah selesai memuat, CPU akan mengalihkan memori ROM internal ke memori baru ini, yang saya sebut Character RAM (CHR-RAM) dan dalam mode ini, PPU akan mulai menggambar grafik yang dinamis, ini mungkin bukan solusi terbaik, tetapi ia bekerja. Akibatnya, memori baru dipasang 128 kilobyte dan dapat menyimpan 1024 karakter masing-masing 8x8 piksel untuk latar belakang dan jumlah karakter yang sama untuk sprite.

Dan akhirnya suaranya
Tangan mencapai suara terakhir. Pada awalnya, saya ingin suara seperti apa yang ada di Uzebox , yaitu, bahwa mikrokontroler menghasilkan 4 saluran suara PWM.
Namun, ternyata saya dapat dengan mudah mendapatkan chip vintage dan saya memesan beberapa chip sintesis FM YM3438, orang-orang ini sepenuhnya kompatibel dengan YM2612 yang digunakan dalam Mega Drive / Genesis. Dengan menginstalnya, Anda bisa mendapatkan Mega Drive musik berkualitas dan efek suara yang dihasilkan oleh mikrokontroler.
Saya menginstal mikrokontroler lain dan menyebutnya SPU (Sound Processor Unit), ia mengontrol YM3438 dan dapat menghasilkan suara sendiri. CPU mengontrolnya melalui memori dual-port, kali ini hanya 2 kilobyte.
Seperti pada unit grafik, unit suara memiliki 128 kilobyte memori untuk menyimpan sampel PCM dan patch suara, CPU memuat data ke dalam memori ini dengan mengakses SPU. Ternyata CPU memberi tahu SPU untuk mengeksekusi perintah dari memori ini atau memperbarui perintah untuk SPU setiap frame.
CPU mengontrol empat saluran PWM melalui empat buffer melingkar di memori SPU. SPU memeriksa buffer ini dan mengeksekusi perintah yang ditulis untuk mereka. Ada juga satu buffer untuk chip sintesis FM.
Secara total, seperti pada grafik, interaksi antara CPU dan SPU berjalan sesuai dengan skema:
- SPU menyalin data dari SPU ke memori internal.
- SPU sedang menunggu interupsi dari PPU (ini untuk sinkronisasi)
- Pada saat bersamaan
- CPU memperbarui buffer saluran PWM dan buffer synthesizer FM.
- SPU menjalankan perintah dalam buffer sesuai dengan data dalam memori internal.
- Seiring dengan semua ini, SPU memperbarui suara PWM pada frekuensi 16 kilohertz.

Apa yang keluar pada akhirnya
Setelah semua blok siap, beberapa pergi ke papan tempat memotong roti.
Untuk blok CPU, saya dapat mengembangkan dan memesan PCB khusus, saya tidak tahu apakah itu layak untuk modul lain, saya pikir saya benar-benar beruntung PCB saya segera berfungsi.
Di papan tempat memotong roti sekarang (sejauh ini) hanya ada suara.
Begini tampilannya hari ini:

Arsitektur
Diagram menggambarkan komponen di setiap blok dan bagaimana mereka berinteraksi satu sama lain. Satu-satunya hal yang tidak ditampilkan adalah sinyal dari PPU ke CPU pada setiap frame sebagai interupsi dan sinyal yang sama yang masuk ke SPU.

- CPU: Zilog Z80 pada 10 MHz
- CPU-ROM: 8KB EEPROM, berisi kode bootloader
- CPU-RAM: 128KB RAM (tersedia 56KB), kode dan data untuk program / game
- IO MCU: Atmega324, adalah antarmuka antara CPU dan RS232, keyboard PS / 2, joystick dan sistem file kartu SD
- PPU-RAM: 4 kilobyte dari memori dual-port, memori antara antara CPU dan PPU
- CHR-RAM: RAM 128KB, menyimpan ubin dinamis untuk mendukung (substrat) dan sprite (dalam karakter 8x8 piksel).
- VRAM1, VRAM2: 128KB RAM (43008 benar-benar tersedia), mereka digunakan untuk framebuffer, mereka menulis PPU dan membaca VPU dari mereka.
- PPU (Picture Processing Unit): Atmega1284, menggambar bingkai ke dalam framebuffer.
- VPU (Video Processing Unit): Atmega324, membaca framebuffer dan menghasilkan sinyal dan sinkronisasi RGB dan PAL.
- SPU-RAM: RAM dual-port 2KB, berfungsi sebagai antarmuka antara CPU dan SPU.
- SNDRAM: 128KB RAM, menyimpan patch PWM, sampel PCM, dan blok instruksi untuk synthesizer FM.
- YM3438: YM3438, chip sintesis FM.
- SPU (Sound Processing Unit): Atmega644, menghasilkan suara berdasarkan prinsip modulasi lebar pulsa (PWM) dan mengontrol YM3438.
Spesifikasi akhir
CPU:
- CPU 8-bit Zilog Z80 pada frekuensi 10Mhz.
- ROM 8KB untuk bootloader.
- RAM 56KB.
IO:
- Membaca data dari pembaca kartu SD FAT16 / FAT32.
- Baca / tulis ke port RS232.
- 2 pengendali game yang kompatibel dengan MegaDrive / Genesis.
- Keyboard PS2.
Video:
- Resolusi 224x192 piksel.
- 25 frame per detik (setengah FPS dari PAL).
- 256 warna (RGB332).
- Latar belakang virtual 2x2 (448x384 piksel), dengan pengguliran berbasis dua arah piksel, berdasarkan pada empat halaman layar penuh.
- 64 sprite dengan lebar dan tinggi 8 atau 16 piksel dengan kemungkinan flip vertikal dan horizontal.
- Latar belakang dan sprite masing-masing terdiri dari karakter 8x8 piksel.
- Memori video simbolik dari 1024 karakter untuk latar belakang dan 1024 untuk sprite.
- 64 bergulir horizontal independen di sepanjang garis yang ditetapkan
- 8 bergulir vertikal independen di sepanjang garis yang ditetapkan
- Hamparan 224x48 piksel dengan transparansi tombol warna opsional.
- Tabel Atribut Latar Belakang.
- RGB dan PAL komposit melalui konektor SCART.
Suara:
- PWM untuk 8 bit dan 4 saluran, dengan bentuk gelombang bawaan: persegi, sinus, gergaji, derau, dll.
- Sampel 8-bit, 8 kHz di salah satu saluran PWM.
- Chip sintesis FM YM3438 sarat dengan instruksi pada frekuensi 50 hertz.
Pengembangan untuk konsol
Bootloader ditulis untuk konsol. Bootloader ditempatkan di ROM CPU dan dapat memakan waktu hingga 8 kilobyte. Ini menggunakan 256 byte RAM pertama. Loader adalah hal pertama yang dijalankan CPU. Diperlukan untuk menunjukkan program-program yang terletak pada kartu SD.
Program-program ini dalam file yang berisi kode yang dikompilasi dan mungkin juga mengandung gambar dan suara.
Setelah memilih program, itu dimuat ke dalam memori CPU, memori CHR dan memori SPU. Setelah itu kode program dijalankan. Ukuran maksimum kode yang dimuat ke konsol adalah 56 kilobyte, selain 256 byte pertama, dan tentu saja Anda perlu memperhitungkan ruang untuk tumpukan dan data.
Dan bootloader ini dan program lain yang ditulis untuk konsol ini dibuat dengan cara yang sama seperti yang dijelaskan di bawah ini.
Pemetaan Memori / IO
Yang penting ketika mengembangkan awalan ini adalah memperhitungkan bagaimana CPU mengakses berbagai blok dan mengalokasikan ruang alamat dengan benar untuk input input dan ruang alamat memori.
CPU mengakses memori akses acak bootloader melalui ruang alamat memori.
Ruang alamat memori

Dan ke PPU-RAM, SPU-RAM dan IO MCU melalui ruang alamat I / O.
Ruang alamat I / O

Seperti yang dapat Anda lihat dari tabel, alamat untuk semua perangkat, IO MCU, PPU dan SPU dialokasikan di dalam ruang alamat I / O.
Manajemen PPU
Dari informasi dalam tabel dapat dilihat bahwa untuk kontrol PPU perlu menulis ke memori PPU yang tersedia di alamat 1000h-1FFFh di ruang alamat I / O.
Alokasi ruang alamat PPU

Status PPU dapat mengambil nilai-nilai berikut:
- Mode Grafik Tertanam
- Mode Grafik Dinamis (CHR-RAM)
- Mode perekaman dalam memori CHR
- Rekaman selesai, menunggu konfirmasi mode dari CPU
Di sini, misalnya, bagaimana Anda dapat bekerja dengan sprite:
Awalan dapat menggambar 64 sprite sekaligus. CPU - 1004h-1143h (320 ), 5 (5 * 64 = 320):
- , : Active, Flipped_X, Flipped_Y, PageBit0, PageBit1, AboveOverlay, Width16, Height16.
- , ( ).
- ( β )
- X
- Y
, , Active 1, X Y , 32/32 , .
.
Misalnya, jika kita perlu menunjukkan angka sprite 10, maka alamatnya adalah 4145 (1004h + (5 x 9)), tulis nilai 1 untuk aktivasi dan koordinat, misalnya, x = 100 dan y = 120, tulis nilai 100 di alamat 4148 dan alamat 4149 nilai 120.
Menggunakan assembler
Salah satu metode pemrograman untuk konsol adalah assembler.
Berikut adalah contoh cara menunjukkan satu sprite dan menghidupkannya sehingga bergerak dan mendorong tepi layar.
ORG 2100h PPU_SPRITES: EQU $1004 SPRITE_CHR: EQU 72 SPRITE_COLORKEY: EQU $1F SPRITE_INIT_POS_X: EQU 140 SPRITE_INIT_POS_Y: EQU 124 jp main DS $2166-$ nmi: ; (NMI) ld bc, PPU_SPRITES + 3 ld a, (sprite_dir) and a, 1 jr z, subX in a, (c) ; X inc a out (c), a cp 248 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a jp updateY subX: in a, (c) ; X dec a out (c), a cp 32 jr nz, updateY ld a, (sprite_dir) xor a, 1 ld (sprite_dir), a updateY: inc bc ld a, (sprite_dir) and a, 2 jr z, subY in a, (c) ; Y inc a out (c), a cp 216 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a jp moveEnd subY: in a, (c) ; Y dec a out (c), a cp 32 jr nz, moveEnd ld a, (sprite_dir) xor a, 2 ld (sprite_dir), a moveEnd: ret main: ld bc, PPU_SPRITES ld a, 1 out (c), a ; 0 inc bc ld a, SPRITE_CHR out (c), a ; 0 inc bc ld a, SPRITE_COLORKEY out (c), a ; 0 inc bc ld a, SPRITE_INIT_POS_X out (c), a ; 0 inc bc ld a, SPRITE_INIT_POS_Y out (c), a ; Y 0 mainLoop: jp mainLoop sprite_dir: DB 0
Menggunakan bahasa C.
Anda juga dapat menggunakan bahasa C, untuk ini kita memerlukan kompiler SDCC dan beberapa utilitas tambahan.
Kode C mungkin lebih lambat, tetapi menulisnya lebih cepat dan lebih mudah.
Berikut adalah contoh kode yang melakukan hal yang sama dengan kode assembler di atas, ia menggunakan pustaka yang membantu membuat panggilan ke PPU:
#include <console.h> #define SPRITE_CHR 72 #define SPRITE_COLORKEY 0x1F #define SPRITE_INIT_POS_X 140 #define SPRITE_INIT_POS_Y 124 struct s_sprite sprite = { 1, SPRITE_CHR, SPRITE_COLORKEY, SPRITE_INIT_POS_X, SPRITE_INIT_POS_Y }; uint8_t sprite_dir = 0; void nmi() { if (sprite_dir & 1) { sprite.x++; if (sprite.x == 248) { sprite_dir ^= 1; } } else { sprite.x--; if (sprite.x == 32) { sprite_dir ^= 1; } } if (sprite_dir & 2) { sprite.y++; if (sprite.y == 216) { sprite_dir ^= 2; } } else { sprite.y--; if (sprite.x == 32) { sprite_dir ^= 2; } } set_sprite(0, sprite); } void main() { while(1) { } }
Grafik dinamis
(Dalam grafis khusus asli. Perkiraan. Per.)
Dalam ROM awalan, 1 halaman ubin untuk pencadangan dan halaman lain dari sprite siap pakai dijahit), secara default Anda hanya dapat menggunakan grafik ini, tetapi Anda dapat beralih ke dinamis.
Tujuan saya adalah agar semua grafik yang diperlukan dalam bentuk biner segera dimuat ke dalam CHR RAM, dan kode dalam bootloader dari ROM dapat melakukan ini. Untuk melakukan ini, saya membuat beberapa gambar dengan ukuran yang benar dengan berbagai simbol bermanfaat:

Karena memori grafis dinamis terdiri dari 4 halaman dengan 256 karakter masing-masing 8x8 piksel dan 4 halaman karakter yang sama untuk sprite, saya mengonversi gambar ke format PNG, menghapus duplikat:

Dan kemudian dia menggunakan alat yang ditulis sendiri untuk menerjemahkan semuanya ke dalam format RGB332 biner dengan blok 8x8.

Sebagai hasilnya, kami memiliki file dengan karakter, di mana semua karakter berjalan berurutan dan masing-masing membutuhkan 64 byte.
Suara
Sampel Wave RAW dikonversi menjadi sampel PCM 8-bit 8-kilohertz.
Tambalan untuk efek suara pada PWM dan musik ditulis dengan instruksi khusus.
Sedangkan untuk chip sintesis Yamaha YM3438 FM, saya menemukan sebuah program yang disebut DefleMask yang menghasilkan musik PAL-disinkronkan untuk chip Genesis YM2612, yang kompatibel dengan YM3438.
DefleMask mengekspor musik dalam format VGM dan saya mengonversinya dengan utilitas milik lain ke dalam format biner saya sendiri.
Semua binari dari ketiga jenis suara digabungkan menjadi satu file biner, yang dapat dibaca oleh bootloader saya dan dimuat ke dalam memori suara RAM SDN.

Tautan ke file final
Kode biner yang dapat dieksekusi, grafik dan suara digabungkan menjadi satu file PRG. File PRG memiliki header di mana semuanya dijelaskan apakah ada data audio dan grafik, berapa banyak yang mereka tempati dan data itu sendiri.
File seperti itu dapat ditulis ke kartu SD, dan bootloader konsol mempertimbangkannya dan mengunduh semuanya ke tempat yang sesuai dan meluncurkan kode yang dapat dieksekusi program.

Emulator
Saya menulis emulator konsol saya di C ++ menggunakan wxWidgets untuk membuatnya lebih mudah dikembangkan untuk itu.
CPU ditiru oleh perpustakaan libz80 .
Fitur telah ditambahkan ke emulator untuk debugging, saya dapat menghentikannya kapan saja dan melakukan debugging perakitan langkah demi langkah, ada pemetaan ke kode sumber dalam C. jika bahasa ini digunakan untuk permainan.
Menurut grafik, saya dapat melihat ke dalam memori video, dalam tabel simbol dan dalam memori CHR itu sendiri.
Berikut adalah contoh program yang berjalan pada emulator dengan alat debugging dihidupkan.

Demo pemrograman
Video-video ini diambil dengan kamera smartphone yang ditujukan untuk layar CRT TV, saya minta maaf atas kualitas gambar yang tidak sempurna.
Interpreter BASIC yang dapat diprogram dari keyboard PS / 2, setelah program pertama, saya menunjukkan cara menulis langsung ke memori PPU melalui ruang alamat I / O dengan mengaktifkan dan memindahkan sprite:
Demo gambar, dalam video ini secara program mengunduh 64 16x16 sprite, dengan latar belakang latar belakang dengan pengguliran dinamis dan overlay yang bergerak di bawah dan di atas sprite:
Demo suara menunjukkan kemampuan suara YM3438 dan PWM, data suara dari demo ini dan musik FM dan suara PWM bersama-sama menempati hampir semua memori suara 128 kilobyte yang tersedia.
Tetris, hampir secara eksklusif fitur latar belakang, musik pada YM3438, efek suara pada patch PWM digunakan untuk grafik.
Kesimpulan
Proyek ini benar-benar mimpi yang menjadi kenyataan, saya telah mengerjakannya selama beberapa tahun, dengan gangguan, melihat waktu luang saya, saya tidak pernah berpikir bahwa saya akan sejauh ini dalam menciptakan konsol video game retro saya sendiri. Tentu saja, itu tidak sempurna, saya jelas bukan ahli dalam bidang elektronik, jelas ada terlalu banyak elemen dalam set-top box, dan tidak diragukan lagi seseorang dapat melakukan lebih baik dan mungkin beberapa pembaca hanya memikirkannya.
Namun tetap saja, dalam proses mengerjakan proyek ini, saya belajar banyak tentang elektronik, konsol game dan desain komputer, bahasa assembly dan hal-hal menarik lainnya, dan yang paling penting saya menerima kepuasan besar dengan bermain game yang saya sendiri tulis pada perangkat keras yang saya kembangkan sendiri dan dikumpulkan.
Saya punya rencana membuat konsol / komputer dan banyak lagi. Sebenarnya, saya sudah membuat set-top box baru, hampir siap, dan itu adalah retro set-top box yang disederhanakan berdasarkan papan FPGA dan beberapa komponen tambahan (dalam jumlah yang jauh lebih kecil daripada dalam proyek ini, tentu saja), idenya adalah menjadi jauh lebih murah dan lebih berulang.
Walaupun saya menulis banyak tentang proyek ini di sini, tidak diragukan lagi banyak yang bisa dibahas, saya hampir tidak menyebutkan bagaimana mesin suara bekerja, bagaimana CPU berinteraksi dengannya, dan ada banyak lagi yang dapat dilakukan tentang sistem grafis dan I / O lainnya serta seluruh konsol akan memberitahu.
Melihat reaksi para pembaca, saya dapat menulis lebih banyak artikel yang berfokus pada pembaruan, rincian tentang blok awalan individu atau proyek lainnya.
Proyek, situs, saluran Youtube yang menginspirasi saya dan membantu saya dengan pengetahuan teknis:
Situs / saluran ini tidak hanya menginspirasi, tetapi juga membantu saya menemukan solusi untuk masalah kompleks yang muncul selama pengerjaan proyek ini.
Terima kasih sudah membaca sampai sini. :)
Jika Anda memiliki pertanyaan atau umpan balik, silakan tulis di komentar di bawah ini (Artikel asli dalam bahasa Inggris di Github. Approx. Per.)