主题 : 在Visual C++ 1.10/2.0环境下编译Mini vMac
义务网评猿
级别: 论坛版主
UID: 50665
精华: 7
发帖: 2924
威望: 13 星
金钱: 385657 浮游币
贡献值: 8748 点
好评度: 10293 点
人气: 760 点
在线时间: 697(时)
注册时间: 2005-08-02
最后登录: 2020-12-17
楼主  发表于: 2010-03-03 23:06

在Visual C++ 1.10/2.0环境下编译Mini vMac

Visual C++ 和微软的其他开发工具一样有很长的历史,其第一个32位版本早在NT 3.1的1993年就正式出现了。Mini vMac 是我在开放源代码的模拟器中所见过代码最为精炼、简洁的,这也使得它具有相当好的移植性。上次搞到32位版本的VC++ 1.10,于是就准备拿这个Mini vMac来玩玩。
首先使用Mini vMac的源代码镜像,在Mini vMac环境中运行Build,用-e msv -ev 6000参数生成一个适合于Visual C++6.0的完整源码zip文档。
把该zip解压开,打开Visual C++ 1.1,在这个源码所在的目录新建一个工程文件。把源码目录下src子目录下的所有.c和.rc添加到工程中。
由于Visual C++ 1.1环境出现在Windows 95之前,和VC6相比,它具有很多限制:
1.shlobj.h不存在。所有和Explorer相关API和ActiveX相关API都不可用。
2.许多Win32的常数宏定义在自带头文件中不存在。
3.OLE2相关的均不可用。
4.winmm API中的一些参数与VC6有很大差别,比如WAVEFORMATEX结构不能用等等。
5.内联函数定义只有__inline。
6.使用IDE生成的makefile中,rc编译器的路径只包括工程文件所在路径。
7.编译器只支持WinMain为Windows应用程序主函数名。
这里仅仅提到了与Mini vMac相关的一些。因此,必须进行修改,才能编译成功。
我大概具体修改了这么一些地方:
1、CNFGGLOB.h中,#define MayInline __forceinline 改为 __inline。
2、MYOSGLUE.c中

1)
必须加入常量VK_APPS、VK_LWIN、VK_RWIN、SPI_SCREENSAVERRUNNING、_MAX_PATH、等一大堆东西(记不清,自己根据错误内容去看吧。。)
2)
typedef HRESULT (WINAPI *SHGetSpecialFolderPathProcPtr) (
    HWND hwndOwner,
    LPTSTR lpszPath,
    int nFolder,
    BOOL fCreate
);
LOCALVAR SHGetSpecialFolderPathProcPtr MySHGetSpecialFolderPath = NULL;
注释掉,加一行LOCALVAR long MySHGetSpecialFolderPath = NULL;
LOCALFUNC blnr HaveMySHGetSpecialFolderPath(void)
{
下面
    if (! DidSHGetSpecialFolderPath) {
        HMODULE hLibModule = LoadLibrary(TEXT("shell32.dll"));
        if (NULL != hLibModule) {
            MySHGetSpecialFolderPath =
                (SHGetSpecialFolderPathProcPtr)
                GetProcAddress(hLibModule,
#if MyUseUni
                    TEXT("SHGetSpecialFolderPathW")
#else
                    TEXT("SHGetSpecialFolderPathA")
#endif
                );
             FreeLibrary(hLibModule);
        }
        DidSHGetSpecialFolderPath = trueblnr;
    }   
也注释掉。这是因为VC1.1不存在shlobj.h,无法使用这些API,而且也不能使用typedef HRESULT (WINAPI *SHGetSpecialFolderPathProcPtr) 这样的方法来自己定义个函数指针,只有干掉了。
3)
#ifndef EnableShellLinks
#define EnableShellLinks 1 改成 0
#endif
快捷方式相关的VC1.1不能用,没办法。
4)
LOCALPROC MySound_Start(void)
中的
WAVEFORMATEX wfex;
改成
PCMWAVEFORMAT wfex;
其初始化部分
        wfex.wFormatTag = WAVE_FORMAT_PCM;
        wfex.nChannels = 1;
        wfex.nSamplesPerSec = SOUND_SAMPLERATE;
        wfex.nAvgBytesPerSec = SOUND_SAMPLERATE;
        wfex.nBlockAlign = 1;
        wfex.wBitsPerSample = 8;
        wfex.cbSize = 0;
改成
        wfex.wf.wFormatTag = WAVE_FORMAT_PCM;
        wfex.wf.nChannels = 1;
        wfex.wf.nSamplesPerSec = SOUND_SAMPLERATE;
        wfex.wf.nAvgBytesPerSec = SOUND_SAMPLERATE;
        wfex.wf.nBlockAlign = 1;
        wfex.wBitsPerSample=8;
5)
LOCALPROC MyAppendSubmenuConvertName(HMENU hMenu,
    HMENU hSubMenu, char *s)
中,
    MENUITEMINFO mii;
注释掉
#if 0改成1
下面的
    memset(&mii, 0, sizeof(MENUITEMINFO));
    mii.cbSize = sizeof(MENUITEMINFO);
    mii.fMask = MIIM_TYPE | MIIM_SUBMENU;
    mii.fType = MFT_STRING;
    mii.hSubMenu = hSubMenu;
    mii.dwTypeData = ts;
    mii.cch = (UINT)_tcslen(ts);
    (void) InsertMenuItem(hMenu, (UINT) -1, TRUE,
        &mii);
注释掉
VC1.1没有InsertMenuItem这个API和MENUITEMINFO结构。
6)int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow)
改成
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPTSTR lpCmdLine, int nCmdShow)

3、CNFGRAPI.h的#include <shlobj.h>注释掉。
令人惊奇的是,我们修改的仅仅是Mini vMac与系统结合的那一部分,其模拟代码根本没有必要修改。
这样修改后,工程设置把警告级别再改下,编译可以得到这样的结果。

经过我的测试,编译出的MVMAC.exe的链接器版本号为3.10,实际可以在Windows NT 3.5以上的系统运行。

VC2.0和VC1.1的SDK差不多,基本可以如法炮制。
目前还有一些问题点:
1、VC1.1(CL 8.0)、VC 2.0(CL 9.0)都不支持__int64,这是Mini vMac II浮点模拟库必须的,因此目前VC1.1无法简单地编译具有FPU模拟功能的Mini vMac II。
2、这样编译的Mini vMac关闭较慢,还没搞清楚怎么回事,
3、VC1.1的链接器在高版本NT系统(如NT4、2000、XP)下工作不正常,生成特别大的exe,需要使用2.0版本的替换。
另外,某论坛上有洋大人问是否能够把这个编译到16位的Windows平台,或者把这个在Win3.1+Win32s上运行,我只能说,前者需要进行大幅修改(程序中大量直接使用int,大量使用32位内存模型的内存分配),而后者据我的测试,连找不到ROM的错误信息都显示不出来,估计是DIB不支持之类的问题。
[ 此帖被yksoft1在2010-03-03 23:12重新编辑 ]
燃烧的热血。。
坚强的意志。。
造就了YKSOFT Systems
http://yksoft1.spaces.live.com