PC-6001VX for IS11T その3

とりあえず画面表示と、[RETURN]キーの入力だけ実装してみました。SDLのイベントループは使わずに、QWidgetを継承してイベントループを処理しています。エミュレータ側のスレッドとは、グローバル変数でデータを渡しています。その2の実装で音も鳴っているようです。

一応、APIレベル4で実装しているので、IS01でも動くのですが、あまりに遅いのでfor IS11Tとしました。(IS11Tでも遅くて実用的ではありません)

f:id:tanam:20130427025929p:image:w360

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) );