在MS-DOS上的C#中运行游戏

我总是很生气,无法在MS-DOS下的C#中运行64位游戏。 今天我修好了。



Windows可执行文件包括两部分:

  1. DOS程序,显示“此程序无法在DOS模式下启动”
  2. Windows 可执行标头

从某种意义上说,所有.exe文件都是DOS程序,但无济于事。 因此,有一天,我在Github上发现了一个项目,该项目比它应有的明星多得多:

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

Dos64-stub是一个小程序,它通过加载可执行文件的Windows部分并将该过程传送到21世纪,来代替无用的消息“无法在DOS下启动”。 “传送”是指设置页面内存并将处理器置于64位模式(“长”)。

首先,我在Windows下使用了我的游戏“ Snake”,该游戏最近在没有依赖项的情况下达到了8 kb:



当然,通常的Windows API方法在DOS中不可用,因此我不得不重写游戏与外界的通信层。 这就是Environment.TickCount现在的样子:

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

当我们有刻度数时,您可以执行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;)); } } 

然后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++; } 

好了,那么一切都很简单:C#编译器-> CoreRT AOT编译器->链接器。 我们告诉链接器使用Dos64-stub而不是生成无用的默认头。



这里是拉取请求形式的整个源代码

Source: https://habr.com/ru/post/zh-CN484854/


All Articles