xkeropi - WinX68k for X


はじめに

MS-Windows版のX68000エミュレータとして WinX68k という有名な物があります。但し、現在(2008.11頃)オリジナルの開発は終了しているようで、 その改良版が WinX68k高速版 として公開されています。

上記のMS-Windows版WinX68kをNONAKA Kimihiro氏がX Window System上に移植されたものが、 xkeropi (WinX68k for X) です。

インストール

インストールは極めて簡単で、 で完了します。その後、~/.keropi/にIPLROM, フォントROM, FDイメージ等を用意して、 xkeropiを起動してください(この辺りはREADME.jaを参照)。

マウス対応

この様に簡単に導入できて魅力的なエミュレータなのですが、SX-Windowを起動 してみたところ、マウスボタンには反応するものの、マウスカーソルの移動が できません。そこでソースを覗いたところ、マウスカーソルの移動イベントに関する ロジックが未完成の様でした。やはりマウスが使えないと、エミュレータの魅力も 半減してしまうので、なんとかロジックを追加してマウスを使えるようにして みました。
diff -cr ../xkeropi-20070206.ORG/x11/mouse.c ./x11/mouse.c
*** ../xkeropi-20070206.ORG/x11/mouse.c	Sat Dec  6 03:07:16 2003
--- ./x11/mouse.c	Thu Nov  6 21:13:54 2008
***************
*** 121,126 ****
--- 121,127 ----
  	int x, y;
  
  	if (MouseSW) {
+ #if 0 /* Change start by Masahiko Ito <m-ito@myh.no-ip.org> */
  		mousex += (MousePosX - (TextDotX / 2)) * Config.MouseSpeed;
  		mousey += (MousePosY - (TextDotY / 2)) * Config.MouseSpeed;
  		x = mousex / 10;
***************
*** 151,156 ****
--- 152,187 ----
  		MousePosY = (TextDotY / 2);
  		getmaincenter(window, &pt);
  		gdk_window_set_pointer(window->window, pt.x, pt.y);
+ #else
+ 		getmaincenter(window, &pt);
+ 		mousex += (MousePosX - pt.x) * Config.MouseSpeed;
+ 		mousey += (MousePosY - pt.y) * Config.MouseSpeed;
+ 		x = mousex / 10;
+ 		y = mousey / 10;
+ 		mousex -= x * 10;
+ 		mousey -= y * 10;
+ 		MouseSt = MouseStat;
+ 
+ 		if (x > 127) {
+ 		        MouseSt |= 0x10;
+ 		        MouseX = 127;
+ 		} else if (x < -128) {
+ 		        MouseSt |= 0x20;
+ 		        MouseX = -128;
+ 		} else
+ 		        MouseX = (signed char)x;
+ 
+ 		if (y > 127) {
+ 		        MouseSt |= 0x40;
+ 		        MouseY = 127;
+ 		} else if (y < -128) {
+ 		        MouseSt |= 0x80;
+ 		        MouseY = -128;
+ 		} else
+ 		        MouseY = (signed char)y;
+ 
+ 		gdk_window_set_pointer(window->window, pt.x, pt.y);
+ #endif /* Change end by Masahiko Ito <m-ito@myh.no-ip.org> */
  	} else {
  		MouseSt = 0;
  		MouseX = 0;
diff -cr ../xkeropi-20070206.ORG/x11/winui.c ./x11/winui.c
*** ../xkeropi-20070206.ORG/x11/winui.c	Wed Feb  7 00:12:06 2007
--- ./x11/winui.c	Thu Nov  6 21:13:37 2008
***************
*** 103,108 ****
--- 103,109 ----
  			 | GDK_BUTTON2_MOTION_MASK	\
  			 | GDK_BUTTON3_MOTION_MASK	\
  			 | GDK_POINTER_MOTION_MASK	\
+ 			 | GDK_POINTER_MOTION_HINT_MASK /* Add by Masahiko Ito <m-ito@myh.no-ip.org> */	\
  			 | GDK_KEY_PRESS_MASK		\
  			 | GDK_KEY_RELEASE_MASK		\
  			 | GDK_BUTTON_PRESS_MASK	\
***************
*** 114,119 ****
--- 115,121 ----
  static gint key_release(GtkWidget *w, GdkEventKey *ev);
  static gint button_press(GtkWidget *w, GdkEventButton *ev);
  static gint button_release(GtkWidget *w, GdkEventButton *ev);
+ static gint motion_notify(GtkWidget *w, GdkEventMotion *ev); /* Add by Masahiko Ito <m-ito@myh.no-ip.org> */
  static gint expose(GtkWidget *w, GdkEventExpose *ev);
  
  static void xmenu_toggle_item(char *name, int onoff, int emitp);
***************
*** 148,153 ****
--- 150,157 ----
  	    GTK_SIGNAL_FUNC(button_press), NULL);
  	gtk_signal_connect(GTK_OBJECT(window), "button_release_event",
  	    GTK_SIGNAL_FUNC(button_release), NULL);
+ 	gtk_signal_connect(GTK_OBJECT(window), "motion_notify_event",
+ 	    GTK_SIGNAL_FUNC(motion_notify), NULL); /* Add by Masahiko Ito <m-ito@myh.no-ip.org> */
  
  	gtk_signal_connect(GTK_OBJECT(drawarea), "expose_event",
  	    GTK_SIGNAL_FUNC(expose), NULL);
***************
*** 279,284 ****
--- 283,317 ----
  			Mouse_Event(2, FALSE);
  			break;
  		}
+ 		return TRUE;
+ 	}
+ 	return FALSE;
+ }
+ 
+ /*
+ 
+    Add by Masahiko Ito <m-ito@myh.no-ip.org>
+ 
+  - Signal: gint GtkWidget::motion_notify_event (GtkWidget *WIDGET,
+           GdkEventMotion *EVENT)
+ */
+ static gint
+ motion_notify(GtkWidget *w, GdkEventMotion *ev)
+ {
+ 	int x, y;
+ 	GdkModifierType state;
+ 
+ 	UNUSED(w);
+ 
+ 	if (ev->type == GDK_MOTION_NOTIFY) {
+ 		if (ev->is_hint){
+ 			gdk_window_get_pointer (ev->window, &x, &y, &state);
+ 		}else{
+ 			x = ev->x;
+ 			y = ev->y;
+ 			state = ev->state;
+ 		}
+ 		Mouse_Event(0, (x << 16) | y);
  		return TRUE;
  	}
  	return FALSE;
とりあえず、動いているようです...。

キーボードマップ対応

一部の記号が正しく入力できなかったので、修正しました。 とりあえず自分の環境(X.org X11R6.9 on Linux)では正しく入力できるようになりました...。
diff -cr ../xkeropi-20070206.ORG/x11/keyboard.c ./x11/keyboard.c
*** ../xkeropi-20070206.ORG/x11/keyboard.c	Sat Dec  6 03:07:16 2003
--- ./x11/keyboard.c	Fri Nov  7 12:31:02 2008
***************
*** 75,88 ****
--- 75,100 ----
  		  NC,  NC,  NC,  NC,  NC,  NC,  NC,  NC,
  	//	    ,    ,    ,    ,    ,    ,    ,    		; 0x18
  		  NC,  NC,  NC,  NC,  NC,  NC,  NC,  NC,
+ #if 0 /* Change start by Masahiko Ito <m-ito@myh.no-ip.org> */
  	//	 SPC,  ! ,  " ,  # ,  $ ,  % ,  & ,  '		; 0x20
  		0x35,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
  	//	  ( ,  ) ,  * ,  + ,  , ,  - ,  . ,  /		; 0x28
  		0x08,0x09,0x27,0x28,0x31,0x0c,0x32,0x33,
+ #else
+ 	//	 SPC,  ! ,  " ,  # ,  $ ,  % ,  & ,  '		; 0x20
+ 		0x35,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
+ 	//	  ( ,  ) ,  * ,  + ,  , ,  - ,  . ,  /		; 0x28
+ 		0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
+ #endif /* Change end by Masahiko Ito <m-ito@myh.no-ip.org> */
  	//	  0 ,  1 ,  2 ,  3 ,  4 ,  5 ,  6 ,  7		; 0x30
  		0x0b,0x02,0x03,0x04,0x05,0x06,0x07,0x08,
+ #if 0 /* Change start by Masahiko Ito <m-ito@myh.no-ip.org> */
  	//	  8 ,  9 ,  ; ,  : ,  < ,  = ,  > ,  ? 		; 0x38
  		0x09,0x0a,0x27,0x28,0x30,0x0c,0x32,0x33,
+ #else
+ 	//	  8 ,  9 ,  : ,  ; ,  < ,  = ,  > ,  ? 		; 0x38
+ 		0x09,0x0a,0x28,0x27,0x31,0x0c,0x32,0x33,
+ #endif /* Change end by Masahiko Ito <m-ito@myh.no-ip.org> */
  	//	  @ ,  A ,  B ,  C ,  D ,  E ,  F ,  G		; 0x40
  		0x1b,0x1e,0x2e,0x2c,0x20,0x13,0x21,0x22,
  	//	  H ,  I ,  J ,  K ,  L ,  M ,  N ,  O		; 0x48
上記のパッチを当てた後に、 ~/.keropi/xkeyconf.datを削除してから xkeropiを起動してください。

xkeropi-20081109.tar.gz

上記までのパッチを反映させた xkeropi-20081109.tar.gz を公開していただきました(NONAKA様ありがとうございます)。ただ、
*** ../xkeropi-20081109.ORG/x11/winui.c	2008-11-08 11:24:18.000000000 +0900
--- x11/winui.c	2008-11-11 16:31:22.000000000 +0900
***************
*** 145,150 ****
--- 145,152 ----
  	    GTK_SIGNAL_FUNC(button_press), NULL);
  	gtk_signal_connect(GTK_OBJECT(window), "button_release_event",
  	    GTK_SIGNAL_FUNC(button_release), NULL);
+ 	gtk_signal_connect(GTK_OBJECT(window), "motion_notify_event",
+ 	    GTK_SIGNAL_FUNC(motion_notify), NULL); /* Add by Masahiko Ito <m-ito@myh.no-ip.org> */
  
  	gtk_signal_connect(GTK_OBJECT(drawarea), "expose_event",
  	    GTK_SIGNAL_FUNC(expose), NULL);
上記のパッチが洩れているようなのでご注意ください。

~/.keropi/configが無い状態で起動すると、MIDI_SetMimpiMap()でセグる

configが無い状態で起動すると各種のパラメータ値が未設定のままで動作しようとするのだが、 その結果ポインタの指す内容がトンデモナイ事になっていたりして具合が良くない様子。
*** ../xkeropi-20081109.ORG/win32api/peace.c	2003-12-06 03:07:15.000000000 +0900
--- win32api/peace.c	2008-11-11 16:32:50.000000000 +0900
***************
*** 365,371 ****
--- 365,378 ----
  
  	fp = fopen(inifile, "r");
  	if (fp == NULL)
+ #if 0 /* Change start by Masahiko Ito <m-ito@myh.no-ip.org> */
  		return 0;
+ #else
+ 	{
+ 		strncpy(buf, defvalue, len);
+ 		return 0;
+ 	}
+ #endif /* Change end by Masahiko Ito <m-ito@myh.no-ip.org> */
  	while (!feof(fp)) {
  		fgets(lbuf, sizeof(lbuf), fp);
  		/* XXX should be case insensitive */
***************
*** 409,415 ****
--- 416,426 ----
  
  	fp = fopen(inifile, "r");
  	if (!fp)
+ #if 0 /* Change start by Masahiko Ito <m-ito@myh.no-ip.org> */
  		return 0;
+ #else
+ 		return defvalue;
+ #endif /* Change end by Masahiko Ito <m-ito@myh.no-ip.org> */
  	while (!feof(fp)) {
  		fgets(lbuf, sizeof(lbuf), fp);
  		/* XXX should be case insensitive */
上記のパッチを当てるとconfigが存在しない場合はデフォルト値が設定されるようになる (ちょこっとした仕様変更)。元々はconfigに存在しないパラメータのみデフォルトが設定 される仕様なのだけれども。

サウンド関係の初期化でエラー

SDL_Init(libsdl)内でこけてる。
ALSA lib confmisc.c:670:(snd_func_card_driver) cannot find card '0'
ALSA lib conf.c:3479:(_snd_config_evaluate) function snd_func_card_driver returned error: そのようなデバイスはありません
ALSA lib confmisc.c:391:(snd_func_concat) error evaluating strings
ALSA lib conf.c:3479:(_snd_config_evaluate) function snd_func_concat returned error: そのようなデバイスはありません
ALSA lib confmisc.c:1070:(snd_func_refer) error evaluating name
ALSA lib conf.c:3479:(_snd_config_evaluate) function snd_func_refer returned error: そのようなデバイスはありません
ALSA lib conf.c:3947:(snd_config_expand) Evaluate error: そのようなデバイスはありません
ALSA lib pcm.c:2146:(snd_pcm_open_noupdate) Unknown PCM default
*** glibc detected *** corrupted double-linked list: 0x089463d8 ***
アボートしました
ハードウェア環境によってはデフォルト値が設定されるとマズイ事もありそう。 でもアボートしている為configが生成されないので毎回デフォルト値が設定され 毎回アボートするというループに...。

上記ALSA初期化エラーの対応

ぶっこける前にとりあえずデフォルト値を~/.keropi/configに書き戻しておく。
*** x11/winx68k.cpp.ORG	2008-11-11 15:55:19.000000000 +0900
--- x11/winx68k.cpp	2008-11-11 15:54:36.000000000 +0900
***************
*** 605,610 ****
--- 605,611 ----
  	file_setcd(winx68k_dir);
  
  	LoadConfig();
+ 	SaveConfig(); /* Add by Masahiko Ito <m-ito@myh.no-ip.org> */
  
  	gtk_set_locale();
  	gtk_rc_add_default_file(".xkeropirc");
一度ぶっこけた後、~/.keropi/configをエディタで編集する。
SampleRate=22050 -> SampleRate=0

カーソルの動きがまだ不審

xkeropiのウィンドウを移動して、ウィンドウの中心点がディスプレイの外に出てると、動きがおかしい。 原因は判ってるのだけれども対処方法を思案中。

xkeropi-20081117.tar.gz

上記までのパッチを反映させた xkeropi-20081117.tar.gz を公開していただきました(NONAKA様ありがとうございます)。
[更新] [戻る]
m-ito@myh.no-ip.org