65.9K
CodeProject 正在变化。 阅读更多。
Home

旧游戏启动器

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.74/5 (14投票s)

2012 年 5 月 31 日

GPL3

4分钟阅读

viewsIcon

36124

downloadIcon

531

用 C# 编写的 DirectDraw 游戏启动器和 DosBox 前端

引言

最近,我一直在尝试玩一些不错的旧游戏,例如《暗黑破坏神I》、《星际争霸》、《帝国时代》。这些游戏的问题在于它们使用 DirectDraw API 进行图形渲染。这很成问题,因为自从 DirectX 10 出现以来,DirectDraw API 仅被模拟,它们没有真正的硬件加速。

现代 CPU 可以毫无速度问题地计算这些基本图形。但是这些游戏只使用 256 位彩色图形。所以如果你尝试运行《帝国时代》或任何旧游戏,颜色将会出错。

这个问题可以很容易地解决。你只需要在开始游戏之前关闭 explorer.exe,然后在游戏结束后再重新执行它。我是一个懒惰的人,所以我决定编写一个应用程序来为我做这件事。在我编写应用程序时,我决定为该程序添加 Dosbox 支持,因为我也喜欢 DOS 游戏,而且我找不到一个像样的前端,这就是旧游戏启动器诞生的原因。

用户界面

该应用程序是用 C# 编写的,用户界面是 Windows Forms。我知道 WPF 更胜一筹,而且是未来,但相比 WPF,我可以用 Windows Forms 更快地设计和编码。在未来的版本中,我可能会使用 WPF 进行重写,但目前 Windows Forms UI 很好地完成了它的工作。

我在 UI 中添加了一些互联网功能,允许单键点击搜索游戏秘籍、维基百科查找或一般的谷歌搜索。

数据管理

该程序以 XML 格式存储游戏配置。XML 是通过 XML 序列化生成的。对于每个游戏,都会存储 3 个属性

  • 游戏名称(string
  • 游戏可执行文件路径(string
  • 一个布尔标志,指示可执行文件需要通过 DosBox 启动

可执行文件的图标不存储,它是动态生成的。如果程序是 Dos 程序,图标就是一个内置的命令行图标,因为 dos 可执行文件不包含任何图标。将来,如果我找到一个像样的游戏图标库,我会添加一个选项为 dos 游戏提供独特的图标。

所有管理例程都定义在 GamesManager 类中。此类负责序列化、图标生成以及与游戏数据管理相关的所有内容。为了保持代码的简单和高效,我在可能的情况下使用了 LINQ。

DosBox 管理

为了使用户更容易,我决定将 DosBox 安装程序嵌入到我的应用程序中。这样,他们只需要安装一个程序。DosBox 作为 zip 文件嵌入在应用程序的资源中。对于 zip 文件提取,我使用 Icsharpcode 的 SharpZipLib 库。该库的 zip 处理例程也内置在该程序的 मुख्य 可执行文件中。

我所有的 DosBox 相关例程都打包在一个名为 FileManager 的类中。该类负责 DosBox 的安装和卸载。程序将 DosBox 安装到名为 oldgameslauncher 的文件夹中。该文件夹在用户的文档目录中创建。这样,安装程序无需管理员权限。与 Old Games Launcher 相关的所有文件也位于此文件夹中,因此很容易备份整个配置。

在程序的未来版本中,我可能会为高级用户添加一个使用自定义 DosBox 安装的选项。

提取代码如下所示

public void InstallDosDox()
{
    try
    {
        MemoryStream ms = new MemoryStream(Properties.Resources.db);
        string basedir = _storageroot + "dosbox";
        string target;
        using (ZipInputStream zi = new ZipInputStream(ms))
        {
            ZipEntry file;
            while ((file = zi.GetNextEntry()) != null)
            {
                target = Path.Combine(basedir, file.Name.Replace('/', '\\'));

                if (file.IsDirectory) Directory.CreateDirectory(target);
                else
                {
                    using (FileStream fs = File.Create(target))
                    {
                        int size;
                        byte[] data = new byte[2048];
                        while ((size = zi.Read(data, 0, data.Length)) > 0)
                        {
                            fs.Write(data, 0, size);
                        }
                    }
                }
            }
        }
    }
    catch (IOException ex)
    {
        MessageBox.Show("DosBox Install failed.\r\n" + 
        ex.Message, "DosBox Installer", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

DdrawHack

Ddraw hack basically 基本上是启动 DirectDraw 应用程序的另一种方法。目前,它是 OpenGlDirectDraw API 的部分重新实现。由于它是部分实现,目前并非适用于所有游戏。但如果它有效,那么在启动游戏之前就不需要关闭 explorer.exe。我添加了一个选项来安装和卸载游戏的 DirectDraw hack。但请注意。这只是一个实验性功能。目前很可能对您的大多数游戏不起作用。

启动可执行文件

启动逻辑显示在以下流程图中。对于等待部分,我使用了一个 Timer 类,该类每秒检查已执行的程序是否正在运行。如果它没有运行,则表示它可以重新启动 explorer.exe

重新启动 explorer.exe 有点棘手。如果 explorer.exe 未运行,而您尝试启动一个名为 explorer.exe 的进程,您最终只会得到一个 Windows Explorer 窗口。这样,您就无法恢复 shell。诀窍在于您必须将进程的工作目录设置为您的 Windows 目录。

关注点

DirectDraw hack 的网站上可以找到关于 DirectDraw 问题的详细文章,地址为  http://sol.gfxile.net/ddhack/

2015-03-14 更新

可以在 https://github.com/webmaster442/old-games-launcher 找到一个稍有更新的版本,其中包含错误修复和更多内容。最初,我计划对程序进行进一步改进,但在过去两年里,我没有足够的时间来处理它。因此,欢迎您 fork 该存储库并使用代码。 :)

© . All rights reserved.