克隆原仓库
使用 VS2022 打开原仓库,首先将构建模式切换成 Release,为了构建游戏,我们不需要 Debug 模式
然后将所有项目在属性页把“警告视为错误”改为否,对照 https://github.com/AmbushedRaccoon/Doom3-BFG-Edition-VS-2019 里面的更改修改文件
这个时候剩下的报错应该只剩下缺少一些库文件 DxErr.h, dxsdkver.h, xma2defs.h
这需要下载 DirectX SDK June 2010,下载链接:
https://www.microsoft.com/en-hk/download/details.aspx?id=6812
直接安装会报错,别人的解决方法:
https://www.cnblogs.com/AI-Algorithms/p/3778527.html
要卸载以下两个程序:
Microsoft Visual C++ 2010 x86 Redistributable
Microsoft Visual C++ 2010 x64 Redistributable
即使下载了,Visual Studio 也不会直接找到 SDK 文件夹,我们我们需要手动配置
如果在安装 SDK 的时候没有更改下载位置,那么默认下载位置应该是 C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)
那么我们就要给项目附加目录
工具->选项->项目和解决方案->VC++ Directorise,然后在右方的 show directorise for 选项中选择include files 选项并把 C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Include此路径加进一新行中,然后在 reference files 和library files 选项中将 C:\Program Files (x86)\Microsoft DirectX SDK (June 2010)\Lib\x64
然后 DirectX 相关的库文件就能找到了,不会报错
接下来是提示找不到 afxres.h
我去看了 https://github.com/electronicarts/CnC_Remastered_Collection/issues/36
然后我尝试换成 #include
没用
尝试下载
C++ MGF v141 生成工具 (x86 & x64)
或
适用于 v142 生成工具的 C++ v14.29 (16.11) MFC (x86 和 x64)
都没有用
于是我找到了 https://www.moddb.com/tutorials/how-to-compile-doom-3-with-visual-studio-2010
根据这里写的,要解决这个问题,需要去 https://www.mediafire.com/?szgoccextjhpig3 下载这个包
然后解压到某个地方
比如我解压到 C:\Program Files (x86)\Microsoft Visual Studio
那么将 C:\Program Files (x86)\Microsoft Visual Studio\atlmfc\include 加入 Doom3BFG 项目的包含目录中,就 Ok 了
然后接下来的错误是
严重性 代码 说明 项目 文件 行 禁止显示状态
错误 RC2133 unexpected value in value data Doom3BFG E:\DOOM-3-BFG\neo\sys\win32\rc\doom.rc 86
错误 RC2132 expected VALUE, BLOCK, or END keyword Doom3BFG E:\DOOM-3-BFG\neo\sys\win32\rc\doom.rc 86
我不懂 RCDATA……不知道哪里错了……之后仔细看才发现,这里有个字符串的引号没了
我打开这个文件的时候,提示我,以简体中文编码打开文件,有的字符被 Unicode 符号替换,我觉得可能是这个引号被换掉了……?
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", "id Software LLC, a ZeniMax Media company"
VALUE "FileDescription", "DOOM 3: BFG Edition"
VALUE "FileVersion", "1.0.0.1"
VALUE "InternalName", "Doom3BFG"
VALUE "LegalCopyright", "?1993-2012 id Software LLC, a ZeniMax Media company"
VALUE "OriginalFilename", "Doom3BFG"
VALUE "ProductName", "DOOM?3: BFG Edition?
VALUE "ProductVersion", "1.0.0.1"
END
END
总之把那个缺少的引号加上,问号应该是识别不了的字符,那我就删掉了,然后就可以运行了
虽然可以运行了,但是 Doom3 窗口会报错 Couldn’t load default.cfg
然后我再看回 https://www.moddb.com/tutorials/how-to-compile-doom-3-with-visual-studio-2010
他说是要把源码目录下的 base 文件夹复制到构建目录中,我试了,复制到构建目录中没有用
于是我根据 Doom3 窗口中的提示,把 base 文件夹复制到了 C:\Users\UserName\Saved Games\id Software\DOOM 3 BFG 中,就可以了
虽然不报 Couldn’t load default.cfg 的错了,但是还有错误
void R_InitOpenGL() {
...
R_SetNewMode( true );
glConfig.renderer_string = (const char *)qglGetString( GL_RENDERER );
qglGetString
是一个函数指针,它的地址为 0x0000 0000 所以报错
这就说明 OpenGL 的函数没有成功的初始化。之后我找到了 OpenGL 的函数在哪初始化了,在 R_SetNewMode 里面的 GLimp_Init,但是这首先要 R_SetNewMode 能够设置一个 mode,如果重复三次不能设置 mode 就会退出这个函数,OpenGL 函数就不能初始化了
// DOOM-3-BFG\neo\renderer\RenderSystem_init.cpp
void R_SetNewMode( const bool fullInit ) {
// try up to three different configurations
for ( int i = 0 ; i < 3 ; i++ ) {
...
if ( r_fullscreen.GetInteger() <= 0 ) {
...
} else {
// get the mode list for this monitor
idList<vidMode_t> modeList;
if ( !R_GetModeListForDisplay( r_fullscreen.GetInteger()-1, modeList ) ) {
idLib::Printf( "r_fullscreen reset from %i to 1 because mode list failed.", r_fullscreen.GetInteger() );
r_fullscreen.SetInteger( 1 );
R_GetModeListForDisplay( r_fullscreen.GetInteger()-1, modeList );
}
if ( modeList.Num() < 1 ) {
idLib::Printf( "Going to safe mode because mode list failed." );
goto safeMode;
}
在这里,R_GetModeListForDisplay
一直不能返回一个非空的 modeList,导致一直进入 safeMode
我再进到 R_GetModeListForDisplay
// DOOM-3-BFG\neo\sys\win32\win_glimp.cpp
for ( int modeNum = 0 ; ; modeNum++ ) {
if ( !EnumDisplaySettings( device.DeviceName,modeNum, &devmode ) ) {
break;
}
if ( devmode.dmBitsPerPel != 32 ) {
continue;
}
//if ( ( devmode.dmDisplayFrequency != 60 ) && ( devmode.dmDisplayFrequency != 120 ) ) {
// continue;
//}
//if ( devmode.dmPelsHeight < 720 ) {
// continue;
//}
if ( verbose ) {
common->Printf( " -------------------\n" );
common->Printf( " modeNum : %i\n", modeNum );
common->Printf( " dmPosition.x : %i\n", devmode.dmPosition.x );
common->Printf( " dmPosition.y : %i\n", devmode.dmPosition.y );
common->Printf( " dmBitsPerPel : %i\n", devmode.dmBitsPerPel );
common->Printf( " dmPelsWidth : %i\n", devmode.dmPelsWidth );
common->Printf( " dmPelsHeight : %i\n", devmode.dmPelsHeight );
common->Printf( " dmDisplayFlags : 0x%x\n", devmode.dmDisplayFlags );
common->Printf( " dmDisplayFrequency : %i\n", devmode.dmDisplayFrequency );
}
vidMode_t mode;
mode.width = devmode.dmPelsWidth;
mode.height = devmode.dmPelsHeight;
// mode.displayHz = devmode.dmDisplayFrequency; // why devmode.dmDisplayFrequency = 0?
mode.displayHz = 144; // hack
modeList.AddUnique( mode );
}
我发现这里返回的 devmode
的 dmDisplayFrequency
, dmPelsHeight
不会满足他的检查条件,并且 devmode.dmDisplayFrequency
还会是 0
我不知道是怎么回事……于是手动把那些条件检查注释掉了,然后用我自己的电脑的屏幕刷新率赋值上去
然后我开始可以进入游戏框了……但是还没运行游戏就开始报错 _default material not found
想设个断点看看哪里读取了 default 设置,没想到这个游戏是直接更改设备分辨率的,导致我断点是断了,但是我卡在那个未响应的游戏窗口那里,鼠标直接没了,Alt Tab 出来也切不到其他应用,更别说还没鼠标了
绝了……直接更改设备的设置,真是坏文明
后来开了第二个桌面,进到第二个桌面之后有鼠标了,才能改回分辨率,然后回到第一个桌面结束进程
通过项目内搜索,找到报错位置:
// DOOM-3-BFG\neo\renderer\RenderSystem_init.cpp
void R_InitMaterials() {
tr.defaultMaterial = declManager->FindMaterial( "_default", false );
if ( !tr.defaultMaterial ) {
common->FatalError( "_default material not found" );
}
这就很奇怪了……难道是我素材文件夹放的不对?
于是我继续看,发现神奇的是,这好像是必定要获得 NULL 的
// DOOM-3-BFG\neo\framework\DeclManager.cpp
const idMaterial *idDeclManagerLocal::FindMaterial( const char *name, bool makeDefault ) {
return static_cast<const idMaterial *>( FindType( DECL_MATERIAL, name, makeDefault ) );
}
// DOOM-3-BFG\neo\framework\DeclManager.cpp
const idDecl *idDeclManagerLocal::FindType( declType_t type, const char *name, bool makeDefault ) {
idDeclLocal *decl;
...
decl = FindTypeWithoutParsing( type, name, makeDefault );
if ( !decl ) {
return NULL;
}
...
}
// DOOM-3-BFG\neo\framework\DeclManager.cpp
idDeclLocal *idDeclManagerLocal::FindTypeWithoutParsing( declType_t type, const char *name, bool makeDefault ) {
...
if ( !makeDefault ) {
// int test = makeDefault;
// common->FatalError("makeDefault: %d", test);
return NULL;
}
...
}
这一路看下去就很神奇啊,只要设置了 makeDefault = false
的话,一定会得到一个 NULL 的
我不理解为什么会这么做……
于是我自己改成了 true
void R_InitMaterials() {
// why set makeDefault = false? When makeDefault = false, it return NULL directly!?
// tr.defaultMaterial = declManager->FindMaterial( "_default", false );
tr.defaultMaterial = declManager->FindMaterial("_default", true);
然后是 Could not load default font 的报错
// DOOM-3-BFG\neo\renderer\Font.cpp
idFont::idFont( const char * n ) : name( n ) {
...
if ( !LoadFont() ) {
if ( name.Icmp( DEFAULT_FONT ) == 0 ) {
idLib::FatalError( "Could not load default font \"%s\"", DEFAULT_FONT );
} else {
idLib::Warning( "Could not load font %s", n );
alias = renderSystem->RegisterFont( DEFAULT_FONT );
}
}
...
}
// DOOM-3-BFG\neo\renderer\Font.cpp
bool idFont::LoadFont() {
idStr fontName = va( "newfonts/%s/48.dat", GetName() );
idFile * fd = fileSystem->OpenFileRead( fontName );
if ( fd == NULL ) {
// common->FatalError("bool idFont::LoadFont(): fd == NULL!");
return false;
}
...
}
我搜了一下 C 盘和源码目录,都没有这个 newfonts 文件夹啊……我无语了……
为什么啊……我有点不理解,这种资源缺失的问题,如果确实有的这样的问题的话,别人应该十年前就会提出来的啊……为什么我完全没有看到这样的记录……
假设我把字体这部分注释掉,然后又有 ERROR: Couldn't load script/doom_main.script
的错误
我感觉好像就是我缺了游戏资产
其实一开始我是没有反应的,因为我看到了一些 shader,我还以为这些就够了,emmm,但是我确实没看到贴图什么的,是我大意了
之后看到 https://gamedev.stackexchange.com/questions/22802/how-can-i-build-and-run-doom-3-from-source-in-windows 才知道,我应该去 steam 购买游戏本体
但是等到我买完之后,我还是没有 newfonts 文件夹……还是没有办法运行……
所以我干脆就不搞了……