とりあえず画面表示と、[RETURN]キーの入力だけ実装してみました。SDLのイベントループは使わずに、QWidgetを継承してイベントループを処理しています。エミュレータ側のスレッドとは、グローバル変数でデータを渡しています。その2の実装で音も鳴っているようです。
一応、APIレベル4で実装しているので、IS01でも動くのですが、あまりに遅いのでfor IS11Tとしました。(IS11Tでも遅くて実用的ではありません)
SIGSEGVでは落ちなくなりましたが画面の初期化で失敗しています。以下をコメントアウトして、とりあえずエミュレータ側のスレッドを実行してしまいます。
graph.cpp
//////////////////////////////////////////////////////////////// // スクリーンサーフェス作成 // // 引数: なし // 返値: bool true:成功 false:失敗 //////////////////////////////////////////////////////////////// bool DSP6::SetScreenSurface( void ) { PRINTD( GRP_LOG, "[GRP][SetScreenSurface]\n" ); int x = 0, y = 0; bool fsflag = false; #ifndef NOMONITOR // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // if( DISPMON ){ // モニタモード? x = P6DEBUGW; y = P6DEBUGH; fsflag = false; PRINTD( GRP_LOG, " -> Monitor Mode ( X:%d Y:%d )\n", x, y ); }else #endif // @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ // { if( DISPFULL ){ // フルスクリーン? // Mac のフルスクリーンは 640x480, 800x600, 1024x768 に限られるらしい。by Windyさん // とりあえず問答無用で640x480に固定してみる x = P6WIFW; y = P6WIFH; fsflag = true; PRINTD( GRP_LOG, " -> FullScreen ( X:%d Y:%d %dbpp)\n", x, y, Bpp ); }else{ x = P6WINW * ( DISPSCAN ? 2 : 1 ); y = ( DISPNTSC ? HBBUS : P6WINH ) * ( DISPSCAN ? 2 : 1 ) + ( DISPSTAT ? vm->el->staw->Height() : 0 ); fsflag = false; PRINTD( GRP_LOG, " -> Window ( X:%d Y:%d %dbpp )\n", x, y, Bpp ); } } // スクリーンサーフェス作成 OSD_CreateWindow( &Wh, x, y, Bpp, fsflag ); /// if( !Wh ) return false; (省略) //////////////////////////////////////////////////////////////// // 画面更新 // // 引数: なし // 返値: なし //////////////////////////////////////////////////////////////// void DSP6::DrawScreen( void ) { PRINTD( GRP_LOG, "[GRP][DrawScreen]\n" ); VSurface *BBuf = vm->vdg; // バックバッファへのポインタ取得 /// if( !Wh || !BBuf ) return;
唯一コーディングした(笑)P6Widgetをmain()で生成してapp.exec()します。画面出力やキーボード入力は、各スレッドの親(pc6001v.cpp)のグローバル変数で実現しています。
P6Widget.cpp
#include "P6Widget.h" extern unsigned char *gBuffer; extern unsigned char *gMatrix; P6Widget::P6Widget(QWidget *) { memset(gMatrix, 0xff, 16*2); } void P6Widget::keyPressEvent(QKeyEvent *event) { qDebug("%d",event->key()); if (event->key() == 16777220) gMatrix[8]=0xfe; // Enter } void P6Widget::keyReleaseEvent(QKeyEvent *event) { memset(gMatrix, 0xff, 16*2); } void P6Widget::paintEvent(QPaintEvent *) { QPainter painter(this); QImage img(static_cast<uchar*>(gBuffer), 720, 540, QImage::Format_RGB16); painter.drawPixmap(70,-30, QPixmap::fromImage(img)); update(); }
P6Widget.h
#ifndef P6WIDGET_H #define P6WIDGET_H #include <QWidget> #include <QKeyEvent> #include <QPainter> class P6Widget : public QWidget { Q_OBJECT public: P6Widget(QWidget *parent = 0); protected: void paintEvent(QPaintEvent *); void keyPressEvent(QKeyEvent *); void keyReleaseEvent(QKeyEvent *); }; #endif // P6WIDGET_H
pc6001v.cpp
#include "P6Widget.h" unsigned char *gBuffer; unsigned char *gMatrix; (省略) /////////////////////////////////////////////////////////// // メイン /////////////////////////////////////////////////////////// int main( int argc, char *argv[] ) { #ifdef SDL_VIDEO_DRIVER_X11 //X11環境でSDLスレッドを使用するために必要。 XInitThreads(); #endif QtSingleApplication app(argc, argv); QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8")); EL6 *P6Core = NULL; // オブジェクトポインタ EL6::ReturnCode Restart = EL6::Quit; // 再起動フラグ CFG6 Cfg; // 環境設定オブジェクト P6Widget* p6w; gBuffer=(unsigned char *)malloc(720*540*2); memset(gBuffer, 0, 720*540*2); gMatrix=(unsigned char *)malloc(16*2); memset(gMatrix, 0, 16*2); (省略) p6w=new P6Widget(); p6w->setStyleSheet("background-color:black;"); p6w->showFullScreen(); // VM実行 P6Core->Start(); app.exec(); /// Restart = P6Core->EventLoop(); P6Core->Stop();
osdSDL.cpp
extern unsigned char *gBuffer; //////////////////////////////////////////////////////////////// // ウィンドウに転送 // // 引数: wh ウィンドウハンドル // src 転送元サーフェス // pal パレットへのポインタ // x,y 転送先座標 // 返値: なし //////////////////////////////////////////////////////////////// void OSD_BlitToWindow( HWINDOW wh, VSurface *src, int x, int y, VPalette *pal ) { /* VRect src1,drc1; if( !src || !wh ) return; #if SDL_VERSION_ATLEAST(2,0,0) SDL_Surface *dst = SDL_GetWindowSurface( (SDL_Window *)wh ); #else SDL_Surface *dst = SDL_GetVideoSurface(); #endif // 転送元範囲設定 src1.x = max( 0, -x ); src1.y = max( 0, -y ); src1.w = min( src->Width() - src1.x, dst->w ); src1.h = min( src->Height() - src1.y, dst->h ); if( src1.w <= 0 || src1.h <= 0 ) return; // 転送先範囲設定 drc1.x = max( 0, x ); drc1.y = max( 0, y ); if( SDL_MUSTLOCK( dst ) ) SDL_LockSurface( dst ); BYTE *psrc = (BYTE *)src->GetPixels() + src->Pitch() * src1.y + src1.x * src->Bpp() / 8; BYTE *pdst = (BYTE *)dst->pixels + dst->pitch * drc1.y + drc1.x * dst->format->BytesPerPixel; if( src->Bpp() == dst->format->BitsPerPixel ){ for( int i=0; i < src1.h; i++ ){ memcpy( pdst, psrc, src1.w * dst->format->BytesPerPixel ); psrc += src->Pitch(); pdst += dst->pitch; } }else if( src->Bpp() == 8 && dst->format->BitsPerPixel == 16 ){ // 8 -> 16 bpp (5:6:5) for( int i=0; i < src1.h; i++ ){ for( int j=0; j < src1.w; j++ ){ WORD wdat = (WORD)(pal->colors[*psrc].r & 0xf8) << 8 | (WORD)(pal->colors[*psrc].g & 0xfc) << 3 | (WORD)(pal->colors[*psrc].b & 0xf8) >> 3; *pdst++ = (BYTE)( wdat & 0xff); *pdst++ = (BYTE)((wdat >> 8) & 0xff); psrc++; } psrc += src->Pitch() - src1.w; pdst += dst->pitch - src1.w * 2; } }else if( src->Bpp() == 8 && dst->format->BitsPerPixel == 24 ){ // 8 -> 24 bpp for( int i=0; i < src1.h; i++ ){ for( int j=0; j < src1.w; j++ ){ *pdst++ = pal->colors[*psrc].b; *pdst++ = pal->colors[*psrc].g; *pdst++ = pal->colors[*psrc].r; psrc++; } psrc += src->Pitch() - src1.w; pdst += dst->pitch - src1.w * 3; } } if( SDL_MUSTLOCK( dst ) ) SDL_UnlockSurface( dst ); */ if (src->Width()==720 && src->Height()==540 && src->Bpp()==16) memcpy(gBuffer, src->GetPixels(), 720 * 540 * 2); }
keyboard.cpp
extern unsigned char *gMatrix; //////////////////////////////////////////////////////////////// // キーマトリクススキャン // // 引数: なし // 返値: true:変化あり false:変化なし //////////////////////////////////////////////////////////////// bool KEY6::ScanMatrix( void ) { PRINTD( KEY_LOG, "[KEY][ScanMatrix] " ); // キーマトリクスを保存 memcpy( P6Matrix, gMatrix, 16 ); memcpy( P6Mtrx, P6Matrix, COUNTOF(P6Mtrx) );