OSDN Git Service

MacOSXでのキーボード入力対応!
[heavyosecpu/HeavyOSECPU.git] / dpndenv.c
1 #include "osecpu.h"\r
2 \r
3 \r
4 #if (DRV_OSNUM == 0x0002)\r
5 //\r
6 // for Mac OSX 32-bit\r
7 //\r
8 #include <mach/mach.h>\r
9 #include <Cocoa/Cocoa.h>\r
10 \r
11 @interface OSECPUView : NSView\r
12 {\r
13         unsigned char *_buf;\r
14         int _sx;\r
15         int _sy;\r
16         CGContextRef _context;\r
17 }\r
18 \r
19 - (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy;\r
20 - (void)drawRect:(NSRect)rect;\r
21 @end\r
22 \r
23 @implementation OSECPUView\r
24 - (id)initWithFrame:(NSRect)frameRect buf:(unsigned char *)buf sx:(int)sx sy:(int)sy\r
25 {\r
26         self = [super initWithFrame:frameRect];\r
27         if (self) {\r
28                 _buf = buf;\r
29                 _sx = sx;\r
30                 _sy = sy;\r
31         }\r
32         return self;\r
33 }\r
34 \r
35 - (void)drawRect:(NSRect)rect {\r
36         CGColorSpaceRef colorSpace;\r
37         CGImageRef image;\r
38         CGContextRef currentContext;\r
39         \r
40         currentContext = [[NSGraphicsContext currentContext] graphicsPort];\r
41         colorSpace= CGColorSpaceCreateDeviceRGB();\r
42         \r
43         // ビットマップコンテキストにvramイメージを生成\r
44         _context = CGBitmapContextCreate (_buf, _sx, _sy, 8, 4 * _sx, colorSpace, (kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst));\r
45         image = CGBitmapContextCreateImage(_context);\r
46         \r
47         // 生成したvramイメージをViewに描画\r
48         CGContextDrawImage(currentContext, NSRectToCGRect(rect), image);\r
49         \r
50         // メモリ解放\r
51         CFRelease(colorSpace);\r
52         CFRelease(image);\r
53 }\r
54 \r
55 - (void)keyDown:(NSEvent *)theEvent\r
56 {\r
57         int i, j;\r
58         unichar kc;\r
59         \r
60         if([[theEvent characters] length] != 1){\r
61                 return;\r
62         }\r
63         \r
64         kc = [[theEvent characters] characterAtIndex:0];\r
65         \r
66         // 通常キー\r
67         i = KEY_EMPTY;\r
68         if (kc == '\r') i = KEY_ENTER;\r
69         if (kc == 0x1b) i = KEY_ESC;\r
70         if (kc == 0x7F)         i = KEY_BACKSPACE;\r
71         if (kc == '\t')         i = KEY_TAB;\r
72         if (kc == NSPageUpFunctionKey)          i = KEY_PAGEUP;\r
73         if (kc == NSPageDownFunctionKey)                i = KEY_PAGEDWN;\r
74         if (kc == NSEndFunctionKey)             i = KEY_END;\r
75         if (kc == NSHomeFunctionKey)            i = KEY_HOME;\r
76         if (kc == NSLeftArrowFunctionKey)               i = KEY_LEFT;\r
77         if (kc == NSRightArrowFunctionKey)              i = KEY_RIGHT;\r
78         if (kc == NSUpArrowFunctionKey)         i = KEY_UP;\r
79         if (kc == NSDownArrowFunctionKey)               i = KEY_DOWN;\r
80         if (kc == NSInsertFunctionKey)  i = KEY_INS;\r
81         if (kc == NSDeleteFunctionKey)  i = KEY_DEL;\r
82         // 修飾キー\r
83         // TODO : 下の方の右辺、iとjが混ざっているのは修正すべき?\r
84         j = 0;\r
85         /*\r
86         if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= KEY_MODIFIER_CONTROL_L;\r
87         if ((GetKeyState(VK_LMENU)    & (1 << 15)) != 0) j |= KEY_MODIFIER_MENU_L;\r
88         if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= KEY_MODIFIER_CONTROL_R;\r
89         if ((GetKeyState(VK_RMENU)    & (1 << 15)) != 0) j |= KEY_MODIFIER_MENU_R;\r
90         if ((GetKeyState(VK_RSHIFT)   & (1 << 15)) != 0) i |= KEY_MODIFIER_SHIFT_R;\r
91         if ((GetKeyState(VK_LSHIFT)   & (1 << 15)) != 0) i |= KEY_MODIFIER_SHIFT_L;\r
92         if ((GetKeyState(VK_NUMLOCK)  & (1 << 0)) != 0) i |= KEY_MODIFIER_NUMLOCK;\r
93         if ((GetKeyState(VK_CAPITAL)  & (1 << 0)) != 0) i |= KEY_MODIFIER_CAPITAL;\r
94          */\r
95         \r
96         NSLog(@"%X", kc);\r
97         if (isascii(kc)){\r
98                 i = kc;\r
99         }\r
100 \r
101         if (i != -1) {\r
102                 putKeybuf(i | j);\r
103         }\r
104 }\r
105 /*\r
106 - (void)keyUp:(NSEvent *)theEvent\r
107 {\r
108         NSLog(@"kUp");\r
109 }\r
110  */\r
111 @end\r
112 \r
113 @interface Main : NSObject<NSWindowDelegate>\r
114 {\r
115         int argc;\r
116         const unsigned char **argv;\r
117         char *winClosed;\r
118         OSECPUView *_view;\r
119         NSWindow *mainWindow;\r
120         NSMenu *mainMenu;\r
121 }\r
122 \r
123 - (void)runApp;\r
124 - (void)createThread:(int)_argc args:(const unsigned char **)_argv;\r
125 - (BOOL)windowShouldClose:(id)sender;\r
126 - (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int)sy winClosed:(char *)_winClosed;\r
127 - (void)flushWin:(NSRect)rect;\r
128 @end\r
129 \r
130 @implementation Main\r
131 - (void)runApp\r
132 {\r
133         // Sub thread\r
134         NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];\r
135         int retv;\r
136         retv = HeavyOSECPUMain(argc, (char **)argv);\r
137         [NSApp terminate:self];\r
138         [pool release];\r
139         exit(retv);\r
140 }\r
141 \r
142 - (void)createThread : (int)_argc args:(const unsigned char **)_argv\r
143 {\r
144         argc = _argc;\r
145         argv = _argv;\r
146         NSThread *thread = [[[NSThread alloc] initWithTarget:self selector:@selector(runApp) object:nil] autorelease];\r
147         [thread start];\r
148 }\r
149 \r
150 - (BOOL)windowShouldClose:(id)sender\r
151 {\r
152         *winClosed = 1;\r
153         return YES;\r
154 }\r
155 \r
156 - (void)windowDidBecomeKey:(NSNotification *)notification\r
157 {\r
158         [mainWindow makeFirstResponder:_view];\r
159 }\r
160 \r
161 - (void)openWin:(unsigned char *)buf sx:(int)sx sy:(int) sy winClosed:(char *)_winClosed\r
162 {\r
163         mainWindow = [[NSWindow alloc] initWithContentRect: NSMakeRect(0, 0, sx, sy) styleMask: NSTitledWindowMask | NSMiniaturizableWindowMask | NSClosableWindowMask backing: NSBackingStoreBuffered defer: NO];\r
164         mainWindow.delegate = self;\r
165         [mainWindow setTitle: @"osecpu"];\r
166         [mainWindow center];\r
167         [mainWindow makeKeyAndOrderFront:self];\r
168         [mainWindow setReleasedWhenClosed:YES];\r
169         \r
170         winClosed = _winClosed;\r
171         \r
172         _view = [[OSECPUView alloc] initWithFrame:NSMakeRect(0,0,sx,sy) buf:buf sx:sx sy:sy];\r
173         [mainWindow.contentView addSubview:_view];\r
174 }\r
175 \r
176 - (void)flushWin : (NSRect)rect\r
177 {\r
178         [_view setNeedsDisplayInRect:rect];\r
179 }\r
180 \r
181 @end\r
182 \r
183 id objc_main;\r
184 \r
185 int main(int argc, char **argv)\r
186 {\r
187         // Main thread\r
188         NSAutoreleasePool* pool;\r
189         ProcessSerialNumber psn = {0, kCurrentProcess};\r
190         \r
191         // ForegroundApplicationになれるように設定(こうしないとキーイベントが取得できない)\r
192         TransformProcessType(&psn, kProcessTransformToForegroundApplication);\r
193                 \r
194         objc_main = [[Main alloc] init];\r
195         NSApp = [NSApplication sharedApplication];\r
196         \r
197         pool = [[NSAutoreleasePool alloc] init];\r
198         [objc_main createThread:argc args:(const unsigned char **)argv];\r
199         [NSApp run];\r
200         [pool release];\r
201         return 0;\r
202 }\r
203 \r
204 void *mallocRWE(int bytes)\r
205 {\r
206         void *p = malloc(bytes);\r
207         vm_protect(mach_task_self(), (vm_address_t) p, bytes, FALSE, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);\r
208         return p;\r
209 }\r
210 \r
211 void drv_openWin(int sx, int sy, unsigned char *buf, char *winClosed)\r
212 {\r
213         [objc_main openWin:buf sx:sx sy:sy winClosed:winClosed];\r
214 }\r
215 \r
216 void drv_flshWin(int sx, int sy, int x0, int y0)\r
217 {\r
218         [objc_main flushWin:NSMakeRect(x0,y0,sx,sy)];\r
219 }\r
220 \r
221 void drv_sleep(int msec)\r
222 {\r
223         [NSThread sleepForTimeInterval:0.001*msec];\r
224         return;\r
225 }\r
226 \r
227 \r
228 #elif (DRV_OSNUM == 0x0003)\r
229 \r
230 #error "Your OS is not supported."\r
231 \r
232 #elif (DRV_OSNUM == 0x0001)\r
233 //\r
234 // for Windows 32-bit\r
235 //\r
236 #include <windows.h>\r
237 \r
238 #define TIMER_ID                         1\r
239 #define TIMER_INTERVAL          10\r
240 \r
241 struct BLD_WORK {\r
242         HINSTANCE hi;\r
243         HWND hw;\r
244         BITMAPINFO bmi;\r
245         int tmcount1, tmcount2, flags, smp; /* bit0: 終了 */\r
246         HANDLE mtx;\r
247         char *winClosed;\r
248 };\r
249 \r
250 struct BLD_WORK bld_work;\r
251 \r
252 struct BL_WIN {\r
253         int xsiz, ysiz, *buf;\r
254 };\r
255 \r
256 struct BL_WORK {\r
257         struct BL_WIN win;\r
258         jmp_buf jb;\r
259         int csiz_x, csiz_y, cx, cy, col0, col1, tabsiz, slctwin;\r
260         int tmcount, tmcount0, mod, rand_seed;\r
261         int *cbuf;\r
262         unsigned char *ftyp;\r
263         unsigned char **fptn;\r
264         int *ccol, *cbak;\r
265         int *kbuf, kbuf_rp, kbuf_wp, kbuf_c;\r
266 };\r
267 \r
268 struct BL_WORK bl_work;\r
269 \r
270 #define BL_SIZ_KBUF                     8192\r
271 \r
272 #define BL_WAITKEYF             0x00000001\r
273 #define BL_WAITKEYNF    0x00000002\r
274 #define BL_WAITKEY              0x00000003\r
275 #define BL_GETKEY               0x00000004\r
276 #define BL_CLEARREP             0x00000008\r
277 #define BL_DELFFF               0x00000010\r
278 \r
279 #define BL_KEYMODE              0x00000000      // 作りかけ, make/remake/breakが見えるかどうか\r
280 \r
281 #define w       bl_work\r
282 #define dw      bld_work\r
283 \r
284 void bld_openWin(int x, int y, char *winClosed);\r
285 void bld_flshWin(int sx, int sy, int x0, int y0);\r
286 LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp);\r
287 void bl_cls();\r
288 int bl_iCol(int i);\r
289 void bl_readyWin(int n);\r
290 \r
291 static HANDLE threadhandle;\r
292 \r
293 int main(int argc, char **argv)\r
294 {\r
295         // Program entry point\r
296         return HeavyOSECPUMain(argc, argv);\r
297 }\r
298 \r
299 void *mallocRWE(int bytes)\r
300 {\r
301         void *p = malloc(bytes);\r
302         DWORD dmy;\r
303         VirtualProtect(p, bytes, PAGE_EXECUTE_READWRITE, &dmy);\r
304         return p;\r
305 }\r
306 \r
307 static int winthread(void *dmy)\r
308 {\r
309         WNDCLASSEX wc;\r
310         RECT r;\r
311         int i, x, y;\r
312         MSG msg;\r
313         \r
314         x = dw.bmi.bmiHeader.biWidth;\r
315         y = -dw.bmi.bmiHeader.biHeight;\r
316         \r
317         wc.cbSize = sizeof (WNDCLASSEX);\r
318         wc.style = CS_HREDRAW | CS_VREDRAW;\r
319         wc.lpfnWndProc = WndProc;\r
320         wc.cbClsExtra = 0;\r
321         wc.cbWndExtra = 0;\r
322         wc.hInstance = dw.hi;\r
323         wc.hIcon = (HICON)LoadImage(NULL, MAKEINTRESOURCE(IDI_APPLICATION),\r
324                                                                 IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
325         wc.hIconSm = wc.hIcon;\r
326         wc.hCursor = (HCURSOR)LoadImage(NULL, MAKEINTRESOURCE(IDC_ARROW),\r
327                                                                         IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED);\r
328         wc.hbrBackground = (HBRUSH)COLOR_APPWORKSPACE;\r
329         wc.lpszMenuName = NULL;\r
330         wc.lpszClassName = "WinClass";\r
331         if (RegisterClassEx(&wc) == 0)\r
332                 return 1;\r
333         r.left = 0;\r
334         r.top = 0;\r
335         r.right = x;\r
336         r.bottom = y;\r
337         AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, FALSE);\r
338         x = r.right - r.left;\r
339         y = r.bottom - r.top;\r
340         \r
341         char *t = "osecpu";\r
342         \r
343         dw.hw = CreateWindowA("WinClass", t, WS_OVERLAPPEDWINDOW,\r
344                                                   CW_USEDEFAULT, CW_USEDEFAULT, x, y, NULL, NULL, dw.hi, NULL);\r
345         if (dw.hw == NULL)\r
346                 return 1;\r
347         ShowWindow(dw.hw, SW_SHOW);\r
348         UpdateWindow(dw.hw);\r
349         SetTimer(dw.hw, TIMER_ID, TIMER_INTERVAL, NULL);\r
350         SetTimer(dw.hw, TIMER_ID + 1, TIMER_INTERVAL * 10, NULL);\r
351         SetTimer(dw.hw, TIMER_ID + 2, TIMER_INTERVAL * 100, NULL);\r
352         dw.flags |= 2 | 4;\r
353         \r
354         for (;;) {\r
355                 i = GetMessage(&msg, NULL, 0, 0);\r
356                 if (i == 0 || i == -1)  /* エラーもしくは終了メッセージ */\r
357                         break;\r
358                 /* そのほかはとりあえずデフォルト処理で */\r
359                 TranslateMessage(&msg);\r
360                 DispatchMessage(&msg);\r
361         }\r
362         //      PostQuitMessage(0);\r
363         dw.flags |= 1; /* 終了, bld_waitNF()が見つける */\r
364         if (dw.winClosed != NULL)\r
365                 *dw.winClosed = 1;\r
366         return 0;\r
367 }\r
368 \r
369 void bld_openWin(int sx, int sy, char *winClosed)\r
370 {\r
371         static int i;\r
372         \r
373         dw.bmi.bmiHeader.biSize = sizeof (BITMAPINFOHEADER);\r
374         dw.bmi.bmiHeader.biWidth = sx;\r
375         dw.bmi.bmiHeader.biHeight = -sy;\r
376         dw.bmi.bmiHeader.biPlanes = 1;\r
377         dw.bmi.bmiHeader.biBitCount = 32;\r
378         dw.bmi.bmiHeader.biCompression = BI_RGB;\r
379         dw.winClosed = winClosed;\r
380         \r
381         threadhandle = CreateThread(NULL, 0, (void *)&winthread, NULL, 0, (void *)&i);\r
382         \r
383         return;\r
384 }\r
385 \r
386 void drv_flshWin(int sx, int sy, int x0, int y0)\r
387 {\r
388         InvalidateRect(dw.hw, NULL, FALSE);\r
389         UpdateWindow(dw.hw);\r
390         return;\r
391 }\r
392 \r
393 LRESULT CALLBACK WndProc(HWND hw, unsigned int msg, WPARAM wp, LPARAM lp)\r
394 {\r
395         int i, j;\r
396         if (msg == WM_PAINT) {\r
397                 PAINTSTRUCT ps;\r
398                 HDC hdc = BeginPaint(dw.hw, &ps);\r
399                 SetDIBitsToDevice(hdc, 0, 0, w.win.xsiz, w.win.ysiz,\r
400                                                   0, 0, 0, w.win.ysiz, w.win.buf, &dw.bmi, DIB_RGB_COLORS);\r
401                 EndPaint(dw.hw, &ps);\r
402         }\r
403         if (msg == WM_DESTROY) {\r
404                 PostQuitMessage(0);\r
405                 return 0;\r
406         }\r
407         if (msg == WM_TIMER && wp == TIMER_ID) {\r
408                 w.tmcount += TIMER_INTERVAL;\r
409                 return 0;\r
410         }\r
411         if (msg == WM_TIMER && wp == TIMER_ID + 1) {\r
412                 dw.tmcount1 += TIMER_INTERVAL * 10;\r
413                 w.tmcount = dw.tmcount1;\r
414                 return 0;\r
415         }\r
416         if (msg == WM_TIMER && wp == TIMER_ID + 2) {\r
417                 dw.tmcount2 += TIMER_INTERVAL * 100;\r
418                 w.tmcount = dw.tmcount1 = dw.tmcount2;\r
419                 return 0;\r
420         }\r
421         if (msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN) {\r
422                 // 通常キー\r
423                 i = KEY_EMPTY;\r
424                 if (wp == VK_RETURN)    i = KEY_ENTER;\r
425                 if (wp == VK_ESCAPE)    i = KEY_ESC;\r
426                 if (wp == VK_BACK)              i = KEY_BACKSPACE;\r
427                 if (wp == VK_TAB)               i = KEY_TAB;\r
428                 if (wp == VK_PRIOR)             i = KEY_PAGEUP;\r
429                 if (wp == VK_NEXT)              i = KEY_PAGEDWN;\r
430                 if (wp == VK_END)               i = KEY_END;\r
431                 if (wp == VK_HOME)              i = KEY_HOME;\r
432                 if (wp == VK_LEFT)              i = KEY_LEFT;\r
433                 if (wp == VK_RIGHT)             i = KEY_RIGHT;\r
434                 if (wp == VK_UP)                i = KEY_UP;\r
435                 if (wp == VK_DOWN)              i = KEY_DOWN;\r
436                 if (wp == VK_INSERT)    i = KEY_INS;\r
437                 if (wp == VK_DELETE)    i = KEY_DEL;\r
438                 // 修飾キー\r
439                 // TODO : 下の方の右辺、iとjが混ざっているのは修正すべき?\r
440                 j = 0;\r
441                 if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= KEY_MODIFIER_CONTROL_L;\r
442                 if ((GetKeyState(VK_LMENU)    & (1 << 15)) != 0) j |= KEY_MODIFIER_MENU_L;\r
443                 if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= KEY_MODIFIER_CONTROL_R;\r
444                 if ((GetKeyState(VK_RMENU)    & (1 << 15)) != 0) j |= KEY_MODIFIER_MENU_R;\r
445                 if ((GetKeyState(VK_RSHIFT)   & (1 << 15)) != 0) i |= KEY_MODIFIER_SHIFT_R;\r
446                 if ((GetKeyState(VK_LSHIFT)   & (1 << 15)) != 0) i |= KEY_MODIFIER_SHIFT_L;\r
447                 if ((GetKeyState(VK_NUMLOCK)  & (1 << 0)) != 0) i |= KEY_MODIFIER_NUMLOCK;\r
448                 if ((GetKeyState(VK_CAPITAL)  & (1 << 0)) != 0) i |= KEY_MODIFIER_CAPITAL;\r
449                 if (j != 0) {\r
450                         if ('A' <= wp && wp <= 'Z'){\r
451                                 i = wp;\r
452                         }\r
453                 }\r
454                 if (i != -1) {\r
455                         putKeybuf(i | j);\r
456                         return 0;\r
457                 }\r
458         }\r
459         if (msg == WM_KEYUP) {\r
460                 i = 0xfff;\r
461         }\r
462         if (msg == WM_CHAR) {\r
463                 i = 0;\r
464                 if (' ' <= wp && wp <= 0x7e) {\r
465                         i = wp;\r
466                         j &= 0;\r
467                         if ((GetKeyState(VK_LCONTROL) & (1 << 15)) != 0) j |= 1 << 17;\r
468                         if ((GetKeyState(VK_LMENU)    & (1 << 15)) != 0) j |= 1 << 18;\r
469                         if ((GetKeyState(VK_RCONTROL) & (1 << 15)) != 0) j |= 1 << 25;\r
470                         if ((GetKeyState(VK_RMENU)    & (1 << 15)) != 0) j |= 1 << 26;\r
471                         if ((GetKeyState(VK_RSHIFT)   & (1 << 15)) != 0) i |= 1 << 24;\r
472                         if ((GetKeyState(VK_LSHIFT)   & (1 << 15)) != 0) i |= 1 << 16;\r
473                         if ((GetKeyState(VK_NUMLOCK)  & (1 << 0)) != 0) i |= 1 << 22;\r
474                         if ((GetKeyState(VK_CAPITAL)  & (1 << 0)) != 0) i |= 1 << 23;\r
475                         if (('A' <= wp && wp <= 'Z') || ('a' <= wp && wp <= 'z')) {\r
476                                 if (j != 0) {\r
477                                         i |= j;\r
478                                         i &= ~0x20;\r
479                                 }\r
480                         }\r
481                         putKeybuf(i);\r
482                         return 0;\r
483                 }\r
484         }\r
485         return DefWindowProc(hw, msg, wp, lp);\r
486 }\r
487 \r
488 void drv_openWin(int sx, int sy, UCHAR *buf, char *winClosed)\r
489 {\r
490         w.win.buf = (int *)buf;\r
491         w.win.xsiz = sx;\r
492         w.win.ysiz = sy;\r
493         bld_openWin(sx, sy, winClosed);\r
494         return;\r
495 }\r
496 \r
497 void drv_sleep(int msec)\r
498 {\r
499         Sleep(msec);\r
500         //      MsgWaitForMultipleObjects(1, &threadhandle, FALSE, msec, QS_ALLINPUT);\r
501         /* 勉強不足でまだ書き方が分かりません! */\r
502         return;\r
503 }\r
504 \r
505 #else\r
506 \r
507 #error "Illegal OS type. Edit osecpu.h and look at DRV_OSNUM"\r
508 \r
509 #endif