/////////////////////////////////////////////////////// /// /// このソースコードを引用・改変した結果如何なる /// 損害が発生しても、著者はは責任を負いません。 /// 広島大学 脳外科 橋詰顕 /// //////////////////////////////////////////////////////// #include //timeGetTime用 #include //timeGetTime 本来windows.hに含まれているはずだが明示しないとだめみたい #pragma comment(lib,"winmm.lib") //wav file用でもある //GIVEIO.sys用 #include //_outpに必要 BOOL CanGIVEIO=TRUE; //GIVEIO.sysを使ってパラレルポートの制御をするかどうか //プロトタイプ BYTE* hnsCopyFileData(char filename[255]); void hnsDeleteWindowMessage(); HANDLE hnsEnableGIVEIO(); void hnsSetFullScreenVGA(HWND hWindow); void hnsTaskLoop(HWND hWindow); void hnsTriggerGIVEIO(int num); LRESULT CALLBACK WindowProcedure(HWND hWindow,UINT message,WPARAM wParameter,LPARAM lParameter); int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow) { //WNDCLASSの設計 WNDCLASS WindowClass; WindowClass.style=CS_HREDRAW | CS_VREDRAW; WindowClass.lpfnWndProc=WindowProcedure; WindowClass.cbClsExtra=0; WindowClass.cbWndExtra=0; WindowClass.hInstance=hInstance; WindowClass.hIcon=LoadIcon(NULL,IDI_APPLICATION); WindowClass.hCursor=LoadCursor(NULL,IDC_ARROW); WindowClass.hbrBackground=(HBRUSH)GetStockObject(BLACK_BRUSH); WindowClass.lpszMenuName=NULL; WindowClass.lpszClassName="WindowClassName"; //設計したWNDCLASSの登録 if(!RegisterClass(&WindowClass)) { MessageBox(NULL,"設計したWNDCLASSの設計に失敗しました","Error!",MB_ICONERROR); return 0; } //Windowの作成 HWND hWindow=CreateWindow( "WindowClassName", //window class name "Let's make MEG task", //title WS_OVERLAPPEDWINDOW | WS_VISIBLE, //Window Style CW_USEDEFAULT,CW_USEDEFAULT, //top left CW_USEDEFAULT,CW_USEDEFAULT, //width,height NULL, //parent window handle (HMENU)NULL, //window menu handle hInstance, //application handle NULL); //creation parameter ShowWindow(hWindow,SW_SHOW); //GIVEIO.sysを有効にする HANDLE h=hnsEnableGIVEIO(); MSG message; //無限ループです。 while(GetMessage(&message,NULL,0,0)) { TranslateMessage(&message); DispatchMessage(&message); } //GIVEIOを終了する。 if(h!=NULL){CloseHandle(h);} return 0; } BYTE* hnsCopyFileData(char filename[255]) { HANDLE hfilename=CreateFile( //ファイルを開く filename, //ファイル名 GENERIC_READ, //アクセスモード 0, //共有モード NULL, //security OPEN_EXISTING, //作成方法 FILE_ATTRIBUTE_NORMAL, //ファイル属性 NULL); //テンプレートファイルのハンドル if(hfilename==INVALID_HANDLE_VALUE) { MessageBox(NULL,"impossible to access target file!","ERROR",MB_ICONERROR); return NULL; } //file情報の取得 BY_HANDLE_FILE_INFORMATION fileinformation; GetFileInformationByHandle(hfilename,&fileinformation); //fileサイズ取得後、ファイルサイズ分のメモリ容量を確保 BYTE* pfile=new BYTE[fileinformation.nFileSizeLow]; DWORD filebytesize1; //確保したメモリに目的のファイルを読み込む ReadFile(hfilename,pfile,fileinformation.nFileSizeLow,&filebytesize1,NULL);//4GBまで CloseHandle(hfilename); return pfile; } void hnsDeleteWindowMessage() { //Window Messageを取り除く MSG message; int flag=1; while (1) { flag=::PeekMessage(&message,NULL,WM_KEYFIRST,WM_KEYLAST,PM_REMOVE ); if(flag==0){break;} } } HANDLE hnsEnableGIVEIO() { if(!CanGIVEIO){return NULL;}//GIVEIOを最初から使わないとき //Windows2000/XPの時のGIVEIO.sysの設定 HANDLE h=CreateFile( (LPCTSTR)"\\\\.\\giveio", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if(h==INVALID_HANDLE_VALUE) { MessageBox(NULL,TEXT("GIVEIOは使えません"),TEXT("GIVEIO.sys check"),MB_ICONERROR); CanGIVEIO=TRUE; } return h; } void hnsSetFullScreenVGA(HWND hWindow) { static int WindowWidth=640; static int WindowHeight=480; LONG lResult; //画面を640x480に変更できたかどうか //画面を640x480にする DEVMODE DeviceMode; DeviceMode.dmSize =sizeof(DEVMODE); DeviceMode.dmFields =DM_PELSWIDTH | DM_PELSHEIGHT; DeviceMode.dmPelsWidth =WindowWidth; DeviceMode.dmPelsHeight =WindowHeight; //画面を元に戻す if(hWindow==NULL){ ChangeDisplaySettings(&DeviceMode,NULL); return; } lResult=ChangeDisplaySettings(&DeviceMode,CDS_FULLSCREEN); if(lResult!=DISP_CHANGE_SUCCESSFUL) { MessageBox(hWindow,"full screenの変換は失敗しました","",MB_ICONERROR); return; } SetWindowPos(hWindow,HWND_TOPMOST,0,0,WindowWidth,WindowHeight,0); } void hnsTaskLoop(HWND hWindow) { //WAV fileの読み込み BYTE* pStandardWavFile=hnsCopyFileData("standard.wav");//標準刺激のWAV file BYTE* pDeviantWavFile =hnsCopyFileData("deviant.wav"); //逸脱刺激のWAV file if((pStandardWavFile==NULL)||(pDeviantWavFile==NULL)){return;} //Window Messageを取り除く hnsDeleteWindowMessage(); int WaitTime=500;//刺激間隔 int frequency=15; int TriggerSignal[]={0,1,2,4,8,16,32};//task srand(timeGetTime()); do //御法度の無限ループ { hnsTriggerGIVEIO(0); Sleep(WaitTime-50+rand()%100); if(rand()%100>frequency) { hnsTriggerGIVEIO(1); PlaySound((LPCSTR)pStandardWavFile,NULL,SND_SYNC | SND_MEMORY); //標準刺激 } else { hnsTriggerGIVEIO(2); PlaySound((LPCSTR)pDeviantWavFile,NULL,SND_SYNC | SND_MEMORY); //逸脱刺激 //逸脱刺激後は強制的に標準刺激にし、かつカウントしない Sleep(WaitTime-50+rand()%100); PlaySound((LPCSTR)pStandardWavFile,NULL,SND_SYNC | SND_MEMORY); //標準刺激 } }while((GetAsyncKeyState(VK_ESCAPE)&0x8000)==0); delete pStandardWavFile; delete pDeviantWavFile; } void hnsTriggerGIVEIO(int num) { //パラレルポートの設定 const unsigned short data_port =0x00378;//D7,D6,D5,D4,D3,D2,D1,D0 const unsigned short status_port =0x00379;//^BSY,^ACK,PE,SLCT,^ERR,・・・,・・・,・・・ //^BSY=0 printer is busy //^ACK=0 ACK受信 //PE=1 ペーパーエンド //^ERR=0 printer error const unsigned short control_port=0x0037A;//・・・,・・・,DIRC,IRQE,SLIN,IPRT,ATFD,STRB //DIRC:ポート方向の切り替え 1:入力 0:出力 //IRQE:ACK割り込み許可    1:許可 0:禁止 //SLIN:プリンタセレクト制御 1:ON 0:OFF //IPRT:プリンタリセット 1:ON 0:OFF //ATFD:オートフィード 1:ON 0:OFF if(!CanGIVEIO){return;} _outp(control_port,0);// control port 出力モードに _outp(data_port,num);// data port 0~255 } LRESULT CALLBACK WindowProcedure(HWND hWindow,UINT message,WPARAM wParameter,LPARAM lParameter) { switch(message) { case WM_CREATE: hnsSetFullScreenVGA(hWindow); break; case WM_KEYDOWN: switch(wParameter) { //ESCAPEキーをおすとWindowを破壊するWM_DESTROYメッセージを送る case VK_ESCAPE: PostMessage(hWindow,WM_DESTROY,0,0); break; //RETURNキーをおすとタスク開始 case VK_RETURN: hnsTaskLoop(hWindow); hnsSetFullScreenVGA(hWindow); break; } break; case WM_DESTROY: //hnsSetFullScreenVGA(NULL); //ないほうがいいみたい PostQuitMessage(0); return 0; } return DefWindowProc(hWindow,message,wParameter,lParameter); }