Jalankan game dalam C # di MS-DOS

Saya selalu kesal karena saya tidak bisa menjalankan game 64-bit di C # di bawah MS-DOS. Hari ini saya memperbaikinya.



Eksekusi Windows terdiri dari dua bagian:

  1. Program untuk DOS yang menampilkan "Program ini tidak dapat dimulai dalam mode DOS"
  2. Header yang dapat dieksekusi Windows

Dalam arti, semua file .exe adalah program DOS, tetapi tidak melakukan apa pun yang berguna. Jadi suatu hari saya menemukan proyek di Github yang layak mendapatkan lebih banyak bintang daripada yang dimiliki:

github.com/Baron-von-Riedesel/Dos64-stub

Dos64-stub adalah program kecil yang menggantikan pesan yang tidak berguna β€œtidak dapat dimulai di bawah DOS” dengan memuat bagian Windows dari file yang dapat dieksekusi dan memindahkan proses ke abad ke-21. Dengan "teleportasi" yang saya maksud adalah mengatur memori halaman dan menempatkan prosesor dalam mode 64-bit ("panjang").

Untuk memulai, saya mengambil game "Snake" di Windows, yang baru-baru ini menyengat hingga 8 kb tanpa ketergantungan:



Tentu saja, metode Windows API yang biasa tidak tersedia di DOS, jadi saya harus menulis ulang lapisan komunikasi game dengan dunia luar. Beginilah tampilan Environment.TickCount sekarang:

 public static unsafe long TickCount64 { [MethodImpl(MethodImplOptions.NoInlining)] get { //    BIOS -   1AH. // ,         "" . //   BIOS -   , //  BIOS    . //   DOS   . //   0x46C       55. uint timerTicks = * (uint *) 0x46C; return (long) timerTicks * 55; } } 

Ketika kami memiliki jumlah kutu, Anda dapat melakukan Thread.Sleep :

 public static unsafe void Sleep(int delayMs) { //     : 0xF4 0xC3 //     : // // hlt // ret ushort hlt = 0xc3f4; long expected = Environment.TickCount64 + delayMs; while(Environment.TickCount64 < expected) { //  ,     ,   //     // (    ) ClassConstructorRunner.Call<int>(new IntPtr(&hlt;)); } } 

Dan kemudian Console.WriteLine :

 public static unsafe void Write(char c) { byte* biosDataArea = (byte*)0x400; //   VRAM,    BIOS byte* vram = (byte*)0xB8000; if(*(biosDataArea + 0x63) == 0xB4) vram = (byte*)0xB0000; //     vram += * (ushort*)(biosDataArea + 0x4E); //        IBM byte b = c switch { 'β”‚' => (byte)0xB3, 'β”Œ' => (byte)0xDA, '┐' => (byte)0xBF, '─' => (byte)0xC4, 'β””' => (byte)0xC0, 'β”˜' => (byte)0xD9, _ => (byte)c, }; // TODO:     BIOS vram[(s_cursorY * 80 * 2) + (s_cursorX * 2)] = b; vram[(s_cursorY * 80 * 2) + (s_cursorX * 2) + 1] = (byte)s_consoleAttribute; // TODO:      ? s_cursorX++; } 

Nah, semuanya sederhana: Kompiler C # -> Kompiler CoreRT AOT -> Linker. Kami memberi tahu linker untuk menggunakan Dos64-stub alih-alih menghasilkan header default yang tidak berguna.



Dan di sini adalah seluruh kode sumber dalam bentuk permintaan tarik .

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


All Articles