win32text.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. // wonbe Win32 text emulation
  2. /* First Created: Nov.4,2000 by Pie Dey Co.,Ltd. */
  3. /* This source code is distributed under GNU General Public License (GPL) */
  4. /* see http://www.gnu.org/ about GPL */
  5. #include <windows.h>
  6. #include <stdio.h>
  7. #include "win32text.h"
  8. #define SCREEN_SIZE_X (224/8)
  9. #define SCREEN_SIZE_Y (144/8)
  10. static WORD screen[SCREEN_SIZE_X][SCREEN_SIZE_Y];
  11. //static WORD lastChar;
  12. static UINT lastVKey;
  13. static HWND hwnd;
  14. static void wmPaint( HWND hWnd, HDC hdc )
  15. {
  16. int x,y;
  17. int xArea, yArea;
  18. RECT rect, rectDraw;
  19. TEXTMETRIC tm;
  20. GetClientRect( hWnd, &rect );
  21. SelectObject( hdc, GetStockObject( SYSTEM_FIXED_FONT ) );
  22. GetTextMetrics( hdc, &tm );
  23. xArea = SCREEN_SIZE_X * tm.tmMaxCharWidth;
  24. yArea = SCREEN_SIZE_Y * tm.tmHeight;
  25. rectDraw.left = (rect.right-rect.left)/2-xArea/2;
  26. rectDraw.top = (rect.bottom-rect.top)/2-yArea/2;
  27. rectDraw.right = (rect.right-rect.left)/2+xArea/2;
  28. rectDraw.bottom = (rect.bottom-rect.top)/2+yArea/2;
  29. FillRect( hdc, &rect, GetStockObject(GRAY_BRUSH) );
  30. FillRect( hdc, &rectDraw, GetStockObject(WHITE_BRUSH) );
  31. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  32. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  33. WORD val;
  34. BYTE str[2];
  35. val = screen[x][y];
  36. if( val >= 0x100 ) {
  37. str[0] = (val >> 8);
  38. str[1] = (val & 0xff);
  39. TextOut( hdc,
  40. rectDraw.left+x*tm.tmMaxCharWidth,
  41. rectDraw.top+y*tm.tmHeight,
  42. str, 2 );
  43. } else {
  44. static char table[] = " !”#$%&’()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[¥]^_`abcdefghijklmnopqrstuvwxyz{|} ̄";
  45. if( val >= 0x20 && val <= 0x7e ) {
  46. TextOut( hdc,
  47. rectDraw.left+x*tm.tmMaxCharWidth,
  48. rectDraw.top+y*tm.tmHeight,
  49. &table[(val-0x20)*2], 2 );
  50. } else {
  51. str[0] = (BYTE)val;
  52. TextOut( hdc,
  53. rectDraw.left+x*tm.tmMaxCharWidth,
  54. rectDraw.top+y*tm.tmHeight,
  55. str, 1 );
  56. }
  57. }
  58. }
  59. }
  60. }
  61. LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  62. {
  63. PAINTSTRUCT ps;
  64. HDC hdc;
  65. switch (message) {
  66. case WM_PAINT:
  67. hdc = BeginPaint(hWnd, &ps);
  68. wmPaint(hWnd,hdc);
  69. EndPaint(hWnd, &ps);
  70. break;
  71. case WM_KEYDOWN:
  72. lastVKey = (WORD)wParam;
  73. break;
  74. //case WM_CHAR:
  75. // lastChar = (WORD)wParam;
  76. // break;
  77. case WM_CLOSE:
  78. return 0; // 閉じちゃ駄目
  79. case WM_DESTROY:
  80. hwnd = NULL;
  81. PostQuitMessage(0);
  82. break;
  83. default:
  84. return (DefWindowProc(hWnd, message, wParam, lParam));
  85. }
  86. return (0);
  87. }
  88. static int createTextInThread()
  89. {
  90. WNDCLASS wc;
  91. wc.style = CS_HREDRAW | CS_VREDRAW;
  92. wc.lpfnWndProc = (WNDPROC)WndProc;
  93. wc.cbClsExtra = 0;
  94. wc.cbWndExtra = 0;
  95. wc.hInstance = GetModuleHandle(NULL);
  96. wc.hIcon = NULL;
  97. wc.hCursor = LoadCursor(NULL, IDC_ARROW);
  98. wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  99. wc.lpszMenuName = NULL;
  100. wc.lpszClassName = "wonbe_win32text";
  101. RegisterClass(&wc);
  102. hwnd = CreateWindow(wc.lpszClassName, "WONBE TEXT", WS_OVERLAPPEDWINDOW,
  103. CW_USEDEFAULT, 0, SCREEN_SIZE_X*16+64, SCREEN_SIZE_Y*20+64,
  104. NULL, NULL, wc.hInstance, NULL);
  105. if( !hwnd ) return FALSE;
  106. clearText();
  107. ShowWindow( hwnd, SW_SHOW );
  108. UpdateWindow( hwnd );
  109. return TRUE;
  110. }
  111. void clearText()
  112. {
  113. int x,y;
  114. if( hwnd == NULL ) return;
  115. for( y=0; y<SCREEN_SIZE_Y; y++ ) {
  116. for( x=0; x<SCREEN_SIZE_X; x++ ) {
  117. screen[x][y] = ' ';
  118. }
  119. }
  120. InvalidateRect( hwnd, NULL, FALSE );
  121. }
  122. void drawChar( int x, int y, unsigned short ch )
  123. {
  124. if( x < 0 ) return;
  125. if( y < 0 ) return;
  126. if( x >= SCREEN_SIZE_X ) return;
  127. if( y >= SCREEN_SIZE_Y ) return;
  128. screen[x][y] = ch;
  129. InvalidateRect( hwnd, NULL, FALSE );
  130. }
  131. void updateText()
  132. {
  133. UpdateWindow( hwnd );
  134. }
  135. void deleteText()
  136. {
  137. if( hwnd == NULL ) return;
  138. DestroyWindow( hwnd );
  139. hwnd = NULL;
  140. }
  141. DWORD WINAPI ThreadFunc( LPVOID lpParam )
  142. {
  143. MSG msg;
  144. createTextInThread();
  145. while (GetMessage(&msg, NULL, 0, 0)) {
  146. TranslateMessage(&msg);
  147. DispatchMessage(&msg);
  148. }
  149. return 0;
  150. }
  151. int createText()
  152. {
  153. DWORD dwThreadId, dwThrdParam = 1;
  154. HANDLE hThread;
  155. //lastChar = 0;
  156. lastVKey = 0;
  157. hThread = CreateThread(
  158. NULL, // no security attributes
  159. 0, // use default stack size
  160. ThreadFunc, // thread function
  161. &dwThrdParam, // argument to thread function
  162. 0, // use default creation flags
  163. &dwThreadId); // returns the thread identifier
  164. return TRUE;
  165. }
  166. unsigned short win32_wait()
  167. {
  168. UINT t;
  169. while( TRUE ) {
  170. // 以下の2行は本当はマルチスレッド的にNGなんだけど
  171. // テスト用環境だから大目に見る
  172. t = lastVKey;
  173. lastVKey = 0;
  174. switch( t ) {
  175. case 'P':
  176. return 0x02; // START BUTTON
  177. case VK_SPACE:
  178. return 0x04; //KEYWORD_SCAN_A;
  179. case VK_ESCAPE:
  180. return 0x08; //KEYWORD_SCAN_B;
  181. case VK_UP:
  182. case 'E':
  183. return 0x10; //KEYWORD_SCAN_X1;
  184. case VK_RIGHT:
  185. case 'D':
  186. return 0x20; //KEYWORD_SCAN_X2;
  187. case VK_DOWN:
  188. case 'X':
  189. return 0x40; //KEYWORD_SCAN_X3;
  190. case VK_LEFT:
  191. case 'S':
  192. return 0x80; //KEYWORD_SCAN_X4;
  193. case 'T':
  194. return 0x100; //KEYWORD_SCAN_Y1;
  195. case 'G':
  196. return 0x200; //KEYWORD_SCAN_Y2;
  197. case 'V':
  198. return 0x400; //KEYWORD_SCAN_Y3;
  199. case 'F':
  200. return 0x800; //KEYWORD_SCAN_Y4;
  201. }
  202. Sleep( 100 );
  203. }
  204. }
  205. unsigned short win32_scan()
  206. {
  207. WORD t;
  208. t = 0;
  209. if( GetAsyncKeyState('P') & 0x8000 ) {
  210. t |= 0x02; // START
  211. }
  212. if( GetAsyncKeyState(VK_SPACE) & 0x8000 ) {
  213. t |= 0x04; // A
  214. }
  215. if( GetAsyncKeyState(VK_ESCAPE) & 0x8000 ) {
  216. t |= 0x08; // B
  217. }
  218. if( GetAsyncKeyState('E') & 0x8000 ) {
  219. t |= 0x10; // X1
  220. }
  221. if( GetAsyncKeyState('D') & 0x8000 ) {
  222. t |= 0x20; // X2
  223. }
  224. if( GetAsyncKeyState('X') & 0x8000 ) {
  225. t |= 0x40; // X3
  226. }
  227. if( GetAsyncKeyState('S') & 0x8000 ) {
  228. t |= 0x80; // X4
  229. }
  230. if( GetAsyncKeyState('T') & 0x8000 ) {
  231. t |= 0x100; // Y1
  232. }
  233. if( GetAsyncKeyState('G') & 0x8000 ) {
  234. t |= 0x200; // Y2
  235. }
  236. if( GetAsyncKeyState('V') & 0x8000 ) {
  237. t |= 0x400; // Y3
  238. }
  239. if( GetAsyncKeyState('F') & 0x8000 ) {
  240. t |= 0x800; // Y4
  241. }
  242. return t;
  243. }
  244. unsigned int win32_get_tick_count()
  245. {
  246. return GetTickCount()/10;
  247. }
  248. void win32_sys_wait( unsigned int val )
  249. {
  250. Sleep( val*10 );
  251. }
  252. static BOOL bPlayingMIDI = FALSE;
  253. static UINT wDeviceID;
  254. DWORD stopMIDIFile(HWND hwnd)
  255. {
  256. if( bPlayingMIDI ) {
  257. mciSendCommand(MCI_ALL_DEVICE_ID, MCI_CLOSE, MCI_WAIT, (DWORD)NULL);
  258. bPlayingMIDI = FALSE;
  259. }
  260. return 0;
  261. }
  262. DWORD playMIDIFile(HWND hWndNotify, LPSTR lpszMIDIFileName)
  263. {
  264. DWORD dwReturn;
  265. MCI_OPEN_PARMS mciOpenParms;
  266. MCI_PLAY_PARMS mciPlayParms;
  267. MCI_STATUS_PARMS mciStatusParms;
  268. //MCI_SEQ_SET_PARMS mciSeqSetParms;
  269. // Open the device by specifying the device and filename.
  270. // MCI will attempt to choose the MIDI mapper as the output port.
  271. mciOpenParms.lpstrDeviceType = "sequencer";
  272. mciOpenParms.lpstrElementName = lpszMIDIFileName;
  273. if (dwReturn = mciSendCommand((MCIDEVICEID)NULL, MCI_OPEN,
  274. MCI_OPEN_TYPE | MCI_OPEN_ELEMENT,
  275. (DWORD)(LPVOID) &mciOpenParms))
  276. {
  277. // Failed to open device. Don't close it; just return error.
  278. return (dwReturn);
  279. }
  280. // The device opened successfully; get the device ID.
  281. wDeviceID = mciOpenParms.wDeviceID;
  282. bPlayingMIDI = TRUE;
  283. // Check if the output port is the MIDI mapper.
  284. mciStatusParms.dwItem = MCI_SEQ_STATUS_PORT;
  285. if (dwReturn = mciSendCommand(wDeviceID, MCI_STATUS,
  286. MCI_STATUS_ITEM, (DWORD)(LPVOID) &mciStatusParms))
  287. {
  288. mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
  289. return (dwReturn);
  290. }
  291. // The output port is not the MIDI mapper.
  292. // Ask if the user wants to continue.
  293. if (LOWORD(mciStatusParms.dwReturn) != MIDI_MAPPER)
  294. {
  295. //printf("Warning: The MIDI mapper is not available.\n");
  296. }
  297. // Begin playback. The window procedure function for the parent
  298. // window will be notified with an MM_MCINOTIFY message when
  299. // playback is complete. At this time, the window procedure closes
  300. // the device.
  301. mciPlayParms.dwCallback = (DWORD) hWndNotify;
  302. if (dwReturn = mciSendCommand(wDeviceID, MCI_PLAY, MCI_NOTIFY,
  303. (DWORD)(LPVOID) &mciPlayParms))
  304. {
  305. mciSendCommand(wDeviceID, MCI_CLOSE, 0, (DWORD)NULL);
  306. return (dwReturn);
  307. }
  308. return (0L);
  309. }
  310. // "テキスト音楽「サクラ」"に含まれるdsakura.dllを用いてMMLを再生します
  311. // サクラは以下より入手できます http://www.text2music.com/
  312. // dsakura.dllが無ければ音が出ないだけで、エラーにはなりません。
  313. void win32_play_mml( const char * mml )
  314. {
  315. static BOOL initialized = FALSE;
  316. static HMODULE hmod = NULL;
  317. static FARPROC pMMLtoMIDI = NULL;
  318. if( !initialized ) {
  319. HMODULE hmod = LoadLibrary("dsakura");
  320. if( hmod != NULL ) {
  321. pMMLtoMIDI = GetProcAddress( hmod, "MMLtoMIDI" );
  322. } else {
  323. printf("LoadLibrary(\"dsakura\") failed\n");
  324. }
  325. initialized = TRUE;
  326. }
  327. if( pMMLtoMIDI != NULL ) {
  328. char errmsg[256];
  329. BOOL b;
  330. stopMIDIFile(hwnd);
  331. b = (*pMMLtoMIDI)(mml,"$$$.mid",errmsg);
  332. if( b == FALSE ) {
  333. printf("dsakura: %s\n",errmsg);
  334. }
  335. playMIDIFile(hwnd, "$$$.mid");
  336. } else {
  337. printf("play: %s\n", mml );
  338. }
  339. }
  340. // end of win32text.c