ユーザ用ツール

X88000

概要

Project X88000において開発・配布されているPC-8801エミュレータ。 ソースコードはPDSとして公開されており自由に改変できる。

Linux対応版とWindows版とがあり、Linux版は音声のサポートがない。

HAL研PCG-8800にPCGおよび音源まで含めて対応している。

高性能な反面、設定可能な項目は少なく、As Isで利用する場合は問題ないが、キーバインドを変更したい、あるいは、イメージファイルの拡張子の対応を増やしたいといったような場合には、ソースに手を入れて再構築する必要がある。

開発が止まって久しいので、Linux版はさておき、Windows版はある程度手を入れないとビルドすらままならない。

改造

ビルド可能にする(Windows版)

Windows版はDirectX7をターゲットに作成されており、Visual Studio 2019 Communityなどではコンパイルすらできない。 とはいえ、いくつかのポイントを修正すればビルド可能であり、現在でも手を入れたバージョンで遊ぶことが可能である。

よくわからないが、Debugフラグで構築したところ、Windows DefencerにTrojan.Script/Wacatac.B!mlと判定され、駆除された。 Releaseフラグで構築すると特に何も言われないので、誤検出ではないかと思うが、不安な方は使わないほうがいいだろう。

修正箇所

  • StdHeader.h:112~117の一連のtypedefを無効化する。
  • コンパイルエラー(LPDWORDに変換できない)を起こすuint32_t宣言の変数をすべてDWORD宣言に変更する。
  • ライブラリdinput.libおよびdinput.dllはそれぞれdinput8.libおよびdinput8.dllに置き換える。
  • DirectInput8 のインスタンスが作成されるようにする。(X88irectX.cpp内376行目付近から – 下記)
#if 0
    typedef HRESULT WINAPI DirectInputCreateProc(
        HINSTANCE, DWORD, IDirectInput**, IUnknown*);
    DirectInputCreateProc* pprocDirectInputCreate = (DirectInputCreateProc*)
        GetProcAddress(,_hlibDInput, "DirectInputCreateA");
    if (pprocDirectInputCreate == NULL) {
        return false;
    }
    HRESULT hResult;
    // Direct Input
    hResult = pprocDirectInputCreate(
        (HINSTANCE)GetModuleHandle(NULL),
        DIRECTINPUT_VERSION, &m_pDI, NULL);
#else
    typedef HRESULT WINAPI DirectInput8CreateProc(HINSTANCE,DWORD,REFIID,LPVOID*,LPUNKNOWN);
    DirectInput8CreateProc *pprocDirectInput8Create = (DirectInput8CreateProc*)
        GetProcAddress(m_hlibDInput, "DirectInput8Create");
    if (pprocDirectInput8Create == NULL)
    {
        return false;
    }
    HRESULT hResult = pprocDirectInput8Create((HINSTANCE)GetModuleHandleW(NULL), DIRECTINPUT8_VERSION, IID_IDrectInput8W, (LPVOID*)&m_pDI, NULL);
#endif
    if (hResult != DI_OK) {
        return false;
    }

(StdHeader.h 160行目付近の #define DIRECTINPUT_VERSION 0x0300 の下に、#define DIRECTINPUT8_VERSION 0x0800を追加しておく。)

以上を修正するとバイナリを得ることができる。

カーソルキーの機能を変える(Windows版)

X88000はエミュレータとしての完成度が高いものの、キーバインドを含め、設定可能な項目が非常に少ない。 ノートPCで遊ぶ場合など、テンキーがない環境では、カーソルキーにテンキーの2,4,6,8あるいは1,2,3,5などを割り当てて、快適にゲームを楽しみたいのだが、これができない。

なので、キー入力処理に手を入れて、カーソルキーの処理を変更する。 なお、ゲームによって、2,4,6,8または1,2,3,5で上下左右の割り当てになっているので、メニューから切り替えられるようにしておく。

カーソルキーの割り付け変更

リソース(メニュー)の作成

リソースエディターで、メニューを追加する。 IDR_MAINMENU(日本語)およびIDR_MAINMENU_E(英語)の二つがあるので、両方に追加する。 X88000カーソルキーメニュー

それぞれのIDシンボルは以下のようにする。

  • IDM_CURSORKEYS_CURSOR
  • IDM_CURSORKEYS_2468
  • IDM_CURSORKEYS_1235

処理タイプフラグの追加

キー処理はX88Frameの中で行われているので、フラグを、X88Frame.cppおよびX88Frame.hに追加していく。

X88Frame.hの93行目からフラグの宣言を追加。

91:    // keyboard state table
92:    static uint8_t m_abtKeyboardState[256];
93:#if 1
94:    // cursor key mapping
95:    static uint8_t m_cursorMode;
96:#endif

X88Frame.cppの122行目からフラグのインスタンスを定義する。

118:// keyboard state table
119:
120:uint8_t CX88Frame::m_abtKeyboardState[256];
121:
122:#if 1
123:// cursor keys
124:uint8_t CX88Frame::m_cursorMode = 0;
125:#endif

メニュー処理の実装

X88Frame.cppCX88Frame::WndProc()処理内に追加(汚い)

		case IDM_VERSION:
			OnHelpMenuCommand(LOWORD(wParam));
			break;
#if 1
		case IDM_CURSORKEYS_CURSOR:
			m_cursorMode = 0;
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_CURSOR, MFS_CHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_2468, MFS_UNCHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_1235, MFS_UNCHECKED);
			break;
		case IDM_CURSORKEYS_2468:
			m_cursorMode = 1;
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_CURSOR, MFS_UNCHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_2468, MFS_CHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_1235, MFS_UNCHECKED);
			break;
		case IDM_CURSORKEYS_1235:
			m_cursorMode = 2;
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_CURSOR, MFS_UNCHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_2468, MFS_UNCHECKED);
			CheckMenuItem(GetMenu(hwnd), IDM_CURSORKEYS_1235, MFS_CHECKED);
			break;
#endif
		}
		break;

本来は、ラジオボタンにするべきだろうが、今時のメニューはどうするべきなのかちゃんとわかってないので、汚い処理になっている。

キー処理の変更

X8Frame.cpp内'' CX88Frame::UpdateAllKeyMatrics()''処理内に以下の変更。

	} else {
		bShift = IsKeyPressed(VK_SHIFT);
	}
#if 0
	bool bUpArrow = IsKeyPressed(VK_UP),
		bRightArrow = IsKeyPressed(VK_RIGHT);
	if (X88k().PC88().Z80Main().GetBasicMode() ==
			CPC88Z80Main::BASICMODE_N80V1)
	{
		if (IsKeyPressed(VK_DOWN)) {
			bShift = bUpArrow = true;
		}
		if (IsKeyPressed(VK_LEFT)) {
			bShift = bRightArrow = true;
		}
	}
#else
	bool bUpArrow = false, bRightArrow = false;
	if (m_cursorMode == 0||IsKeyPressed(VK_CONTROL))
	{
		bUpArrow = IsKeyPressed(VK_UP);
		bRightArrow = IsKeyPressed(VK_RIGHT);
		if (X88k().PC88().Z80Main().GetBasicMode() ==
			CPC88Z80Main::BASICMODE_N80V1)
		{
			if (IsKeyPressed(VK_DOWN)) {
				bShift = bUpArrow = true;
			}
			if (IsKeyPressed(VK_LEFT)) {
				bShift = bRightArrow = true;
			}
		}
	}
	else
	{
		if (IsKeyPressed(VK_DOWN) || IsKeyPressed(VK_LEFT) || IsKeyPressed(VK_RIGHT) || IsKeyPressed(VK_UP))
		{
			if (m_cursorMode == 1)
			{
				X88k().SetKeyMatrics(0x00, 2, IsKeyPressed(VK_DOWN));
				X88k().SetKeyMatrics(0x00, 4, IsKeyPressed(VK_LEFT));
				X88k().SetKeyMatrics(0x00, 6, IsKeyPressed(VK_RIGHT));
				X88k().SetKeyMatrics(0x01, 0, IsKeyPressed(VK_UP));
			}
			else
			{
				X88k().SetKeyMatrics(0x00, 2, IsKeyPressed(VK_DOWN));
				X88k().SetKeyMatrics(0x00, 1, IsKeyPressed(VK_LEFT));
				X88k().SetKeyMatrics(0x00, 3, IsKeyPressed(VK_RIGHT));
				X88k().SetKeyMatrics(0x00, 5, IsKeyPressed(VK_UP));
			}
			return;
		}
	}
#endif
	X88k().SetKeyMatrics(0x00, 0, IsKeyPressed(VK_NUMPAD0));
	X88k().SetKeyMatrics(0x00, 1, IsKeyPressed(VK_NUMPAD1));
...
        }
        else
        {
            bShift = IsKeyPressed(DIK_LSHIFT, DIK_RSHIFT);
        }
#if 0
        bool bUpArrow = IsKeyPressed(DIK_UP),
            bRightArrow = IsKeyPressed(DIK_RIGHT);
        if (X88k().PC88().Z80Main().GetBasicMode() ==
                CPC88Z80Main::BASICMODE_N80V1)
        {
            if (IsKeyPressed(DIK_DOWN)) {
                bShift = bUpArrow = true;
            }
            if (IsKeyPressed(DIK_LEFT)) {
                bShift = bRightArrow = true;
            }
        }
#else
	bool bUpArrow = false, bRightArrow = false;
	if (m_cursorMode == 0||IsKeyPressed(DIK_LCONTROL, DIK_RCONTROL))
	{
		bUpArrow = IsKeyPressed(DIK_UP);
		bRightArrow = IsKeyPressed(DIK_RIGHT);
		if (X88k().PC88().Z80Main().GetBasicMode() ==
			CPC88Z80Main::BASICMODE_N80V1)
		{
			if (IsKeyPressed(DIK_DOWN)) {
				bShift = bUpArrow = true;
			}
			if (IsKeyPressed(DIK_LEFT)) {
				bShift = bRightArrow = true;
			}
		}
	}
	else
	{
		if (IsKeyPressed(DIK_DOWN) || IsKeyPressed(DIK_LEFT) || IsKeyPressed(DIK_RIGHT) || IsKeyPressed(DIK_UP))
		{
			if (m_cursorMode == 1)
			{
				X88k().SetKeyMatrics(0x00, 2, IsKeyPressed(DIK_DOWN));
				X88k().SetKeyMatrics(0x00, 4, IsKeyPressed(DIK_LEFT));
				X88k().SetKeyMatrics(0x00, 6, IsKeyPressed(DIK_RIGHT));
				X88k().SetKeyMatrics(0x01, 0, IsKeyPressed(DIK_UP));
			}
			else
			{
				X88k().SetKeyMatrics(0x00, 2, IsKeyPressed(DIK_DOWN));
				X88k().SetKeyMatrics(0x00, 1, IsKeyPressed(DIK_LEFT));
				X88k().SetKeyMatrics(0x00, 3, IsKeyPressed(DIK_RIGHT));
				X88k().SetKeyMatrics(0x00, 5, IsKeyPressed(DIK_UP));
			}
			return;
		}
	}
#endif
        X88k().SetKeyMatric(0x00, 0, IsKeyPressed(DIK_NUMPAD0));

#if 0で無効化しているのがもともとのカーソルキー処理。 PC-8001などは、カーソルキーが縮退1)しているので、その処理をしている。 ここで、m_cursorModeが0かコントロールキーが押されていたら、カーソルキーとして処理し、そうでなければ、テンキーの振りをするだけである。

1)
上下と左右がそれぞれ一つのキーにまとめられ、シフトキーの有無で向きを変えていた。

This website uses cookies. By using the website, you agree with storing cookies on your computer. Also, you acknowledge that you have read and understand our Privacy Policy. If you do not agree, please leave the website.

More information