PC6001VX 2.0a2がリリースされました。
http://eighttails.seesaa.net/article/305067428.html#more
SDLが切り離されたことで軽くなったはずなので、今度はIS01(Android 1.6)向けにビルドしてみました。Androidに対応したQt5.0.2がリリースされていないため、実績のあるNecessitas Qt 4.8.2 for Androidにバックポートして行きます。
※ Qt 5.1.0 Android for arm(GCC 4.7 Qt 5.1.0)でのビルド手順を反映しました(2013/07/09)
※ Qt 5.1.1 for Androidでも動作確認しました。5.1.0と全く同じでした(2013/09/26)
期待出来るのは以下です。
- メニュー表示
- スキャンライン表示
- ステータスバー表示
- レジューム対応
逆に以下の制限はあると思います。
- NecessitasではOpenGLを使うためには、APIレベル7(GLES2.0)が必要(古い機種ではそのままでは動かない)
- NecessitasではMultimediaは実装されていない(サウンド機能はそのままでは動かない)
http://community.kde.org/Necessitas/FAQ#I_need_Audio_support
以下のオプションで制限を回避します。ジョイスティックもないので、SDLも切り離します。
DEFINES += NOJOYSTICK NOOPENGL
例によってソースファイルを解凍してPC6001VX.proを修正します。
PC6001VX_2.0a2_src.tar.gz
#------------------------------------------------- # # Project created by QtCreator 2012-01-01T00:17:09 # #------------------------------------------------- QT += core gui network TARGET = PC6001VX TEMPLATE = app DEFINES += NOJOYSTICK NOOPENGL INCLUDEPATH += src/Qt src/Qt/qtsingleapplication SOURCES += \ src/breakpoint.cpp \ src/config.cpp \ src/cpum.cpp \ src/cpus.cpp \ src/d88.cpp \ src/debug.cpp \ src/device.cpp \ src/disk.cpp \ src/error.cpp \ src/graph.cpp \ src/ini.cpp \ src/intr.cpp \ src/io.cpp \ src/joystick.cpp \ src/keyboard.cpp \ src/memory.cpp \ src/movie.cpp \ src/p6t2.cpp \ src/pio.cpp \ src/psg.cpp \ src/replay.cpp \ src/schedule.cpp \ src/sound.cpp \ src/status.cpp \ src/tape.cpp \ src/vdg.cpp \ src/voice.cpp \ src/vsurface.cpp \ src/device/ay8910.cpp \ src/device/mc6847.cpp \ src/device/pd7752.cpp \ src/device/pd8255.cpp \ src/device/z80.cpp \ src/device/z80-dbg.cpp \ src/Qt/osdQt.cpp \ src/Qt/pc6001v.cpp \ src/Qt/configdialog.cpp \ src/Qt/colorbutton.cpp \ src/Qt/aboutdialog.cpp \ src/Qt/common.cpp \ src/Qt/console.cpp \ src/p6el.cpp \ src/p6vm.cpp \ src/Qt/qtsingleapplication/qtlocalpeer.cpp \ src/Qt/qtsingleapplication/qtlockedfile.cpp \ src/Qt/qtsingleapplication/qtlockedfile_unix.cpp \ src/Qt/qtsingleapplication/qtlockedfile_win.cpp \ src/Qt/qtsingleapplication/qtsingleapplication.cpp \ src/Qt/qtsingleapplication/qtsinglecoreapplication.cpp \ src/Qt/qtp6vxapplication.cpp \ src/Qt/emulationadaptor.cpp \ src/Qt/renderview.cpp \ src/Qt/qtel6.cpp \ src/Qt/semaphore.cpp \ src/Qt/thread.cpp HEADERS += \ src/breakpoint.h \ src/common.h \ src/config.h \ src/console.h \ src/cpum.h \ src/cpus.h \ src/d88.h \ src/debug.h \ src/device.h \ src/disk.h \ src/error.h \ src/graph.h \ src/ini.h \ src/intr.h \ src/io.h \ src/joystick.h \ src/keyboard.h \ src/keydef.h \ src/log.h \ src/memory.h \ src/movie.h \ src/osd.h \ src/p6device.h \ src/p6t2.h \ src/pc6001v.h \ src/pio.h \ src/psg.h \ src/replay.h \ src/schedule.h \ src/semaphore.h \ src/sound.h \ src/status.h \ src/tape.h \ src/thread.h \ src/typedef.h \ src/vdg.h \ src/voice.h \ src/vsurface.h \ src/device/ay8910.h \ src/device/mc6847.h \ src/device/pd7752.h \ src/device/pd8255.h \ src/device/z80.h \ src/device/z80-cdCB.h \ src/device/z80-cdED.h \ src/device/z80-cdXC.h \ src/device/z80-cdXX.h \ src/device/z80-code.h \ src/device/z80-tbl.h \ src/Qt/configdialog.h \ src/Qt/colorbutton.h \ src/Qt/aboutdialog.h \ src/event.h \ src/p6el.h \ src/p6vm.h \ src/Qt/qtsingleapplication/QtLockedFile \ src/Qt/qtsingleapplication/QtSingleApplication \ src/Qt/qtsingleapplication/qtlocalpeer.h \ src/Qt/qtsingleapplication/qtlockedfile.h \ src/Qt/qtsingleapplication/qtsingleapplication.h \ src/Qt/qtsingleapplication/qtsinglecoreapplication.h \ src/Qt/qtp6vxapplication.h \ src/Qt/emulationadaptor.h \ src/Qt/renderview.h \ src/Qt/qtel6.h FORMS += \ src/Qt/configdialog.ui \ src/Qt/aboutdialog.ui OTHER_FILES += \ TODO.txt \ src/Qt/res/PC-6001.ico \ src/Qt/res/PC-6001mk2.ico \ src/Qt/res/PC-6001mk2SR.ico \ src/Qt/res/PC-6601.ico \ src/Qt/res/PC-6601SR.ico \ src/Qt/res/fontz12.png \ src/win32/PC6001VX.ico \ src/win32/PC6001VX.rc \ COPYING \ README.txt \ src/Qt/res/font/fonth12.png \ src/Qt/res/font/fontz12.png \ android/AndroidManifest.xml \ android/res/drawable/icon.png \ android/res/drawable/logo.png \ android/res/drawable-hdpi/icon.png \ android/res/drawable-ldpi/icon.png \ android/res/drawable-mdpi/icon.png \ android/res/layout/splash.xml \ android/res/values/libs.xml \ android/res/values/strings.xml \ android/res/values-de/strings.xml \ android/res/values-el/strings.xml \ android/res/values-es/strings.xml \ android/res/values-et/strings.xml \ android/res/values-fa/strings.xml \ android/res/values-fr/strings.xml \ android/res/values-id/strings.xml \ android/res/values-it/strings.xml \ android/res/values-ja/strings.xml \ android/res/values-ms/strings.xml \ android/res/values-nb/strings.xml \ android/res/values-nl/strings.xml \ android/res/values-pl/strings.xml \ android/res/values-pt-rBR/strings.xml \ android/res/values-ro/strings.xml \ android/res/values-rs/strings.xml \ android/res/values-ru/strings.xml \ android/res/values-zh-rCN/strings.xml \ android/res/values-zh-rTW/strings.xml \ android/src/org/kde/necessitas/ministro/IMinistro.aidl \ android/src/org/kde/necessitas/ministro/IMinistroCallback.aidl \ android/src/org/kde/necessitas/origo/QtActivity.java \ android/src/org/kde/necessitas/origo/QtApplication.java \ android/version.xml RESOURCES += \ src/Qt/pc6001vx.qrc
※ Qt 5.1.0 Androidでも、Multimediaを有効にするとうまく動かなかった。Multimediaはまだ限定的なサポートのようです。
ビルドしてみてエラーを消していきます。QT5関連のエラーは以下の#ifで対処します。
common.cpp、qtel6.cpp
#include <QtCore> #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include <QtGui> #else #include <QtWidgets> #endif
renderview.cpp
#ifndef NOOPENGL #include <QtOpenGL> #endif (省略) #ifndef NOOPENGL if(qApp->property("TILTEnabled").toBool()){ rotate(qApp->property("TILT").toReal()); } #endif
pc6001v.cpp
int main( int argc, char *argv[] ) { #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) QtP6VXApplication app(argc, argv); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); #else //X11の場合 if (QGuiApplication::platformName() == QLatin1String("xcb")){ QCoreApplication::setAttribute(Qt::AA_X11InitThreads); } QtP6VXApplication app(argc, argv); #endif setlocale(LC_ALL,"Japanese");
qtp6vxapplication.cpp
#include <QtCore> #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include <QtGui> #else #include <QtWidgets> #endif (省略) bool QtP6VXApplication::notify ( QObject * receiver, QEvent * event ) { Event ev; ev.type = EV_NOEVENT; switch(event->type()){ case QEvent::KeyPress: case QEvent::KeyRelease: { QKeyEvent* ke = dynamic_cast<QKeyEvent*>(event); Q_ASSERT(ke); int keyCode = ke->key(); // 「ろ」が入力できない対策 quint32 nativeKey = ke->nativeScanCode(); #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #else //X11の場合 if (QGuiApplication::platformName() == QLatin1String("xcb")){ if(keyCode == Qt::Key_Backslash){ keyCode = nativeKey == 97 ? Qt::Key_Underscore : Qt::Key_Backslash; } } //Windowsの場合 else if (QGuiApplication::platformName() == QLatin1String("windows")){ if(keyCode == Qt::Key_Backslash){ keyCode = nativeKey == 115 ? Qt::Key_Underscore : Qt::Key_Backslash; } } #endif
osdQt.cpp
#include <QtCore> #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #include <QtGui> #else #include <QtWidgets> #endif #ifndef Q_OS_ANDROID #include <QtMultimedia> #endif (省略) #ifndef Q_OS_ANDROID //サウンド関連 QPointer<QIODevice> audioBuffer = NULL; QPointer<QAudioOutput> audioOutput = NULL; #endif (省略) //////////////////////////////////////////////////////////////// // オーディオデバイスオープン // // 引数: obj 自分自身へのオブジェクトポインタ // callback コールバック関数へのポインタ // rate サンプリングレート // sample バッファサイズ(サンプル数) // 返値: bool true:成功 false:失敗 //////////////////////////////////////////////////////////////// bool OSD_OpenAudio( void *obj, CBF_SND callback, int rate, int samples ) { #ifndef Q_OS_ANDROID QAudioFormat format; format.setCodec("audio/pcm"); format.setChannelCount(1); format.setSampleRate(rate); format.setSampleSize(16); format.setByteOrder(QAudioFormat::LittleEndian); format.setSampleType(QAudioFormat::SignedInt); if(audioOutput){ audioOutput->deleteLater(); } QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice()); if (!info.isFormatSupported(format)) { qWarning()<<"raw audio format not supported by backend, cannot play audio."; return false; } audioOutput = new QAudioOutput(info, format, qApp); #endif return true; } //////////////////////////////////////////////////////////////// // オーディオデバイスクローズ // // 引数: なし // 返値: なし //////////////////////////////////////////////////////////////// void OSD_CloseAudio( void ) { #ifndef Q_OS_ANDROID if(audioOutput){ audioOutput->stop(); } #endif } //////////////////////////////////////////////////////////////// // 再生開始 // // 引数: なし // 返値: なし //////////////////////////////////////////////////////////////// void OSD_StartAudio( void ) { #ifndef Q_OS_ANDROID if(audioOutput){ audioBuffer = audioOutput->start(); //#PENDING これではグローバルボリュームを変えてしまう? audioOutput->setVolume(0.3); } #endif } //////////////////////////////////////////////////////////////// // 再生停止 // // 引数: なし // 返値: なし //////////////////////////////////////////////////////////////// void OSD_StopAudio( void ) { #ifndef Q_OS_ANDROID if(audioOutput){ audioOutput->suspend(); } #endif } //////////////////////////////////////////////////////////////// // オーディオストリーム書き込み // // 引数: stream 書き込むデータへのポインタ // samples 書き込むバイト数 // 返値: なし //////////////////////////////////////////////////////////////// void OSD_WriteAudioStream(BYTE *stream, int samples) { #ifndef Q_OS_ANDROID if(audioBuffer){ audioBuffer->write((const char*)stream, samples); } #endif } //////////////////////////////////////////////////////////////// // 再生状態取得 // // 引数: なし // 返値: bool true:再生中 false:停止中 //////////////////////////////////////////////////////////////// bool OSD_AudioPlaying( void ) { #ifndef Q_OS_ANDROID return audioOutput->state() == QAudio::ActiveState; #else return false; #endif }
たった、これだけの変更でビルドが通って実行出来ました。例によって、設定ファイル(/sdcard/pc6001v/pc6001vx.ini)を事前に準備して起動させてみます。
//////////////////////////////////////////////////////////////// // 設定及び諸ファイル(ROMなどの初期位置)パス取得 // // 引数: なし // 返値: char * 取得した文字列へのポインタ //////////////////////////////////////////////////////////////// const char *OSD_GetConfigPath( void ) { PRINTD( OSD_LOG, "[OSD][OSD_GetModulePath]\n" ); static char mpath[PATH_MAX] = ""; // モジュールパス取得用 //Windowsの場合はexe本体と同じ場所。 //それ以外(UNIX系を想定)は ~/.pc6001vx を返す #ifdef WIN32 QString confPath = qApp->applicationDirPath() + QDir::separator(); #else #ifdef Q_OS_ANDROID QString confPath = QString("/sdcard/pc6001v"); #else QString confPath = QDir::homePath() + QDir::separator() + QString(".pc6001vx"); #endif #endif sprintf( mpath, "%s", confPath.toUtf8().data() ); AddDelimiter( mpath ); // 念のため UnDelimiter( mpath ); return mpath; }
何か画面ちっちゃいですが、ステータスバーが表示されています。なおサウンド機能は、PC6001VX for IS11Tその2を見ながら、VX1.1のソースコードを移植したら鳴りましたが、動作が重くなるのであえて移植しない方針とします。