OSDN Git Service

キーボード関連の構造体化
[heavyosecpu/HeavyOSECPU.git] / main.c
1 #include "osecpu.h"\r
2 \r
3 HOSECPU_Device_Window mainWindow;\r
4 HOSECPU_Device_Keyboard mainKeyboard;\r
5 HOSECPU_RuntimeEnvironment *dbg_env;\r
6 \r
7 unsigned char *Init_LoadSysLib(char argv0[]);\r
8 void LoadAppBin(HOSECPU_RuntimeEnvironment *env);\r
9 \r
10 int HeavyOSECPUMain(int argc, char **argv)\r
11 {\r
12         HOSECPU_RuntimeEnvironment env;\r
13         unsigned char *pAppJITBin;\r
14         unsigned char *appBinDevFuncBase;\r
15         unsigned char *pSyslibJITBin;\r
16         unsigned char *syslibJITBinBase;\r
17         HOSECPU_LabelListTag *label;\r
18         HOSECPU_PointerControlTag *ptrCtrl;\r
19         // For decoder work\r
20         unsigned char *bufP06;  // P06  UINT8   >=2M\r
21         unsigned int *bufP0A;   // P0A  UINT32  16K\r
22         int *pxxFlag;                   // P0B  SINT32  64\r
23         int *typLabel;                  // P0C  SINT32  4K\r
24         unsigned char *opTbl;   // P0D  UINT8   256\r
25         // For tek decomp\r
26         unsigned char *tekDecompTemp;\r
27         // time counter\r
28         double tm0, tm1, tm2;\r
29         // options from arguments\r
30         int argDebugMode = 0;\r
31         int argStackSize = 1;\r
32         //\r
33         int i;\r
34         const char *s;\r
35         unsigned char *p;\r
36         FILE *fp;\r
37         \r
38         //\r
39         // Initialize\r
40         //\r
41         \r
42         // For debug\r
43         dbg_env = &env;\r
44         // Initialize mainWindow\r
45         mainWindow.vram = NULL;\r
46         mainWindow.xsize = 0;\r
47         mainWindow.ysize = 0;\r
48         // Initialize keyInputting\r
49         mainKeyboard.buf = malloc(KEYBUFSIZ * sizeof(int));\r
50         mainKeyboard.r = 0;\r
51         mainKeyboard.w = 0;\r
52         mainKeyboard.c = 0;\r
53         // Initialize HOSECPU_RuntimeEnvironment\r
54         env.mainArgc = argc;\r
55         env.mainArgv = (const char **)argv;\r
56         //\r
57         env.appOSECPUBin = malloc(APPBINSIZE);\r
58         env.appOSECPUBackendBin = malloc(APPBINSIZE);\r
59         //\r
60         env.appJITBin = mallocRWE(APPJITSIZE);\r
61         pAppJITBin = env.appJITBin;\r
62         env.syslibJITBin = mallocRWE(SYSLIBJITSIZE);\r
63         pSyslibJITBin = env.syslibJITBin;\r
64         // syslibJITBin image:\r
65         // env.syslibJITBin             + - - - -\r
66         //                                              | errHndl\r
67         // syslibJITBinBase             + - - - -\r
68         //                                              | syslib\r
69         //\r
70         env.executionLevel = JITC_LV_SLOWEST;\r
71         // For decoder work\r
72         bufP06 = malloc(DECODER_BUF06_SIZE);\r
73         bufP0A = malloc(DECODER_BUF0A_SIZE);\r
74         pxxFlag = malloc(64 * 4);\r
75         typLabel = malloc(4096 * 4);\r
76         opTbl = malloc(256);\r
77         //\r
78         label = malloc(JITC_MAXLABELS * sizeof (HOSECPU_LabelListTag));\r
79         ptrCtrl = malloc(PTRCTRLSIZ * sizeof (HOSECPU_PointerControlTag));\r
80         for (i = 0; i < PTRCTRLSIZ; i++) {\r
81                 ptrCtrl[i].liveSign = 0;\r
82                 ptrCtrl[i].size = -1;\r
83         }\r
84         ptrCtrl[0].size = -2;\r
85         //\r
86         randStatInit((unsigned int)time(NULL));\r
87         \r
88         //\r
89         // Load syslib\r
90         //\r
91         \r
92         env.syslibOSECPUBin = Init_LoadSysLib(argv[0]);\r
93         \r
94         pSyslibJITBin = jitCompInit(pSyslibJITBin);\r
95         syslibJITBinBase = pSyslibJITBin;\r
96         // labelはjitc0()内で初期化される。\r
97         i = jitc0(&pSyslibJITBin, env.syslibJITBin + SYSLIBJITSIZE, env.syslibOSECPUBin + 32, env.syslibOSECPUBin + SYSLIBBINSIZE, JITC_LV_SLOWEST + 9, label);\r
98         if (i != 0){\r
99                 fputs("syslib-file JITC error.\n", stderr);\r
100                 return 1;\r
101         }\r
102         \r
103         //\r
104         // Load app\r
105         //\r
106         \r
107         LoadAppBin(&env);\r
108         \r
109         tm0 = clock() / (double)CLOCKS_PER_SEC;\r
110         \r
111         if (env.appOSECPUBin[2] == 0xf0) {\r
112                 // tek5圧縮がかかっている\r
113 #if (USE_TEK5 != 0)\r
114                 tekDecompTemp = malloc(TEKDECOMPTMPSIZE);\r
115                 env.appOSECPUBinSize = tek5Decomp(env.appOSECPUBin + 2, env.appOSECPUBin + APPBINSIZE, tekDecompTemp);\r
116                 free(tekDecompTemp);\r
117                 env.appOSECPUBinSize += 2;\r
118 #else\r
119                 env.appOSECPUBinSize = -9;\r
120 #endif\r
121                 if (env.appOSECPUBinSize < 0) {\r
122                         fputs("unsupported-format(tek5)\n", stderr);\r
123                         return 1;\r
124                 }\r
125         }\r
126         //デバッグモード指定\r
127         s = searchArg(argc, (const char **)argv, "debug:", 0);\r
128         if (s != NULL){\r
129                 argDebugMode = *s - '0';\r
130         }\r
131         //スタックサイズ指定(MiB単位)\r
132         s = searchArg(argc, (const char **)argv, "stack:", 0);\r
133         if (s != NULL){\r
134                 argStackSize = strtol(s, NULL, 0);\r
135         }\r
136         \r
137         /* フロントエンドコードをバックエンドコードに変換する */\r
138         if ((env.appOSECPUBin[2] & 0xf0) != 0) {                                // 3バイト目が00なら処理しない\r
139                 env.appOSECPUBackendBin[0] = env.appOSECPUBin[0];\r
140                 env.appOSECPUBackendBin[1] = env.appOSECPUBin[1];\r
141                 env.preg[2].p = &env.appOSECPUBackendBin[2];\r
142                 env.preg[3].p = &env.appOSECPUBackendBin[APPBINSIZE];\r
143                 env.preg[4].p = &env.appOSECPUBin[2];\r
144                 env.preg[5].p = &env.appOSECPUBin[env.appOSECPUBinSize];\r
145                 env.preg[6].p = bufP06;\r
146                 env.preg[7].p = bufP06 + DECODER_BUF06_SIZE;\r
147                 env.preg[0x0A].p = (unsigned char *)bufP0A;\r
148                 env.preg[0x0B].p = (void *)pxxFlag;\r
149                 env.preg[0x0C].p = (void *)typLabel;\r
150                 env.preg[0x0D].p = opTbl;\r
151                 jitcRunBinary((void *)syslibJITBinBase, &env);\r
152                 if (env.ireg[0] != 0) {\r
153                         p = env.preg[2].p - 1;\r
154                         fprintf(stderr, "unpack error: %02X (at %06X) (R00=%d)\n", *p, p - env.appOSECPUBackendBin, env.ireg[0]);\r
155                         if ((argDebugMode & 2) != 0) {\r
156                                 fp = fopen("debug2.bin", "wb");\r
157                                 fwrite(env.appOSECPUBackendBin, 1, p - env.appOSECPUBackendBin + 16, fp);\r
158                                 fclose(fp);\r
159                         }\r
160                         exit(1);\r
161                 }\r
162                 env.appOSECPUBackendBinSize = env.preg[2].p - env.appOSECPUBackendBin;\r
163         } else{\r
164                 memcpy(env.appOSECPUBackendBin, env.appOSECPUBin, env.appOSECPUBinSize);\r
165                 env.appOSECPUBackendBinSize = env.appOSECPUBinSize;\r
166         }\r
167         \r
168         if ((argDebugMode & 2) != 0) {\r
169                 /*変換後のバックエンドコードをファイルへ保存*/\r
170                 fp = fopen("debug2.bin", "wb");\r
171                 fwrite(env.appOSECPUBackendBin, 1, env.appOSECPUBackendBinSize, fp);\r
172                 fclose(fp);\r
173         }\r
174         \r
175         //JITコンパイル\r
176         i = jitc0(&pAppJITBin, env.appJITBin + APPJITSIZE, env.appOSECPUBackendBin, env.appOSECPUBackendBin + APPBINSIZE, env.executionLevel, label);\r
177         if (i == 1){\r
178                 fputs("app-file header error.\n", stderr);\r
179                 return 1;\r
180         }\r
181         if (i != 0){\r
182                 return 1;\r
183         }\r
184         \r
185         env.appJITBinSize = pAppJITBin - env.appJITBin;\r
186         \r
187         // 末尾にAPI関数呼び出しコードを追加\r
188         appBinDevFuncBase = pAppJITBin;\r
189         pAppJITBin = jitCompCallFunc(pAppJITBin, &devFunc);\r
190         \r
191         tm1 = clock() / (double)CLOCKS_PER_SEC;\r
192         \r
193         /* レジスタ初期化 */\r
194         for (i = 0; i < 64; i++){\r
195                 env.ireg[i] = 0;\r
196         }\r
197         for (i = 0; i < 64; i++) {\r
198                 env.preg[i].p = NULL;\r
199                 env.preg[i].typ = -1;\r
200                 env.preg[i].p0 = NULL;\r
201                 env.preg[i].p1 = NULL;\r
202         }\r
203         \r
204         env.buf0 = env.buf1 = NULL;\r
205         \r
206         // p28にapiをコールするアドレスを設定\r
207         env.preg[0x28].p = appBinDevFuncBase;   // appBinDevFuncBaseには、devFuncをコールするコードが書かれている\r
208         env.preg[0x28].typ = 0; // TYP_CODE\r
209         env.preg[0x28].p0 = appBinDevFuncBase;          // アドレス演算できる範囲を制限\r
210         env.preg[0x28].p1 = appBinDevFuncBase + 1;      // アドレス演算できる範囲を制限\r
211         \r
212         //env.preg[0x00].p = malloc(1024 * 1024) + (1024 * 1024 - 32);\r
213         env.junkStack = malloc(argStackSize << 20);\r
214         env.junkStack1 = env.junkStack + (argStackSize << 20);\r
215         env.winClosed = 0;\r
216         env.autoSleep = 0;\r
217         env.lastConsoleChar = '\n';\r
218         \r
219         env.label = label;\r
220         env.maxLabels = JITC_MAXLABELS;\r
221         env.jitbuf = pAppJITBin;\r
222         env.jitbuf1 = env.appJITBin + APPJITSIZE;\r
223         env.errHndl = &errorHandler;\r
224         env.appReturnCode = 0;\r
225         \r
226         env.dbgr = 0;\r
227         if (searchArg(argc, (const char **)argv, "dbgr:1", 0) != NULL){\r
228                 env.dbgr = 1;\r
229         }\r
230         \r
231         if ((argDebugMode & 1) != 0) {\r
232                 fp = fopen("debug1.bin", "wb");\r
233                 fwrite(env.appJITBin, 1, pAppJITBin - env.appJITBin, fp);\r
234                 fclose(fp);\r
235         }\r
236         \r
237         /* JITコード実行 */\r
238         if (setjmp(env.setjmpEnv) == 0){\r
239                 jitcRunBinary((void *)env.appJITBin, &env);\r
240         }\r
241         if (env.autoSleep != 0) {\r
242                 if (mainWindow.vram != NULL){\r
243                         drv_flshWin(mainWindow.xsize, mainWindow.ysize, 0, 0);\r
244                 }\r
245                 while (env.winClosed == 0){\r
246                         drv_sleep(100);\r
247                 }\r
248         }\r
249         if (env.lastConsoleChar != '\n'){\r
250                 putchar('\n');\r
251         }\r
252         \r
253         tm2 = clock() / (double)CLOCKS_PER_SEC;\r
254         \r
255         /* 実行結果確認のためのレジスタダンプ */\r
256         if (searchArg(argc, (const char **)argv, "verbose:1", 0) != NULL) {\r
257                 printf("time: JITC=%.3f[sec], exec=%.3f[sec]\n", tm1 - tm0, tm2 - tm1);\r
258                 printf("size: OSECPU=%d, decomp=%d, native=%d\n", env.appOSECPUBinSize, env.appOSECPUBackendBinSize, env.appJITBinSize);\r
259                 printf("result:\n");\r
260                 printf("R00:0x%08X  R01:0x%08X  R02:0x%08X  R03:0x%08X\n", env.ireg[0], env.ireg[1], env.ireg[2], env.ireg[3]);\r
261         }\r
262 #if (USE_DEBUGGER != 0)\r
263         dbgrMain(&env);\r
264 #endif\r
265         return env.appReturnCode;\r
266         \r
267         return 0;\r
268 }\r
269 \r
270 unsigned char *Init_LoadSysLib(char argv0[])\r
271 {\r
272         unsigned char *syslib;\r
273         FILE *fp;\r
274         unsigned char *up;\r
275         int appsize;\r
276         unsigned char *tmpWorkMemory;\r
277         \r
278         /* syslibの読み込み */\r
279         syslib = malloc(SYSLIBBINSIZE);\r
280         fp = fopen(SYSLIB_OSE, "rb");\r
281         if (fp == NULL) {\r
282                 syslib[0] = '/';\r
283                 strcpy((char *)syslib + 1, argv0);\r
284                 up = syslib + 1;\r
285                 while (*up != '\0'){\r
286                         up++;\r
287                 }\r
288                 while (*up != '/' && *up != 0x5c){\r
289                         up--;\r
290                 }\r
291                 up++;\r
292                 strcpy((char *)up, SYSLIB_OSE);\r
293                 fp = fopen((char *)syslib + 1, "rb");\r
294         }\r
295         if (fp == NULL) {\r
296                 fputs("syslib-file fopen error.\n", stderr);\r
297                 exit(EXIT_FAILURE);\r
298         }\r
299         appsize = fread(syslib, 1, SYSLIBBINSIZE - 4, fp);\r
300         fclose(fp);\r
301         if (appsize >= SYSLIBBINSIZE - 4) {\r
302                 fputs("syslib-file too large.\n", stderr);\r
303                 exit(EXIT_FAILURE);\r
304         }\r
305         if (syslib[0] == 0x05 && syslib[1] == 0xc1) {\r
306                 // maklib のライブラリ形式である。\r
307                 tmpWorkMemory = malloc(SYSLIBDECOMPTMPSIZE);\r
308                 memcpy(tmpWorkMemory, syslib, appsize);\r
309                 ComLib_main(tmpWorkMemory + 2, syslib + 2);\r
310                 free(tmpWorkMemory);\r
311                 //\r
312                 syslib[0] = 0x05;\r
313                 syslib[1] = 0x1b;\r
314         }\r
315         \r
316         fp = fopen("syslib_dbg.ose", "wb");\r
317         fwrite(syslib, 1, SYSLIBBINSIZE, fp);\r
318         fclose(fp);\r
319         return syslib;\r
320 }\r
321 \r
322 void LoadAppBin(HOSECPU_RuntimeEnvironment *env)\r
323 {\r
324         FILE *fp;\r
325         const char *fileName;\r
326         /* アプリバイナリの読み込み */\r
327         if (env->mainArgc <= 1) {\r
328                 //アプリ名未指定なので何事もなく終了\r
329                 exit(EXIT_SUCCESS);\r
330         }\r
331         fileName = env->mainArgv[1];\r
332         //アプリ名先頭に:n:をつけることでレベルnでの実行が可能?\r
333         if (fileName[0] == ':' && fileName[2] == ':') {\r
334                 env->executionLevel = fileName[1] - '0';\r
335                 if (env->executionLevel < 0 || env->executionLevel > 9){\r
336                         env->executionLevel = JITC_LV_SLOWEST;\r
337                 }\r
338                 fileName += 3;\r
339         }\r
340         \r
341         fp = fopen(fileName, "rb");\r
342         if (fp == NULL) {\r
343                 fputs("app-file load error.\n", stderr);\r
344                 exit(EXIT_FAILURE);\r
345         }\r
346         env->appOSECPUBinSize = fread(env->appOSECPUBin, 1, APPBINSIZE - 4, fp);\r
347         fclose(fp);\r
348         \r
349         if (env->appOSECPUBinSize >= APPBINSIZE - 4) {\r
350                 fputs("app-file too large.\n", stderr);\r
351                 exit(EXIT_FAILURE);\r
352         }\r
353         if (env->appOSECPUBinSize < 3) {\r
354                 fputs("app-file header error.\n", stderr);\r
355                 exit(EXIT_FAILURE);\r
356         }\r
357 }\r
358 \r
359 void putKeybuf(int i)\r
360 {\r
361         // TODO : あふれた場合のことを考慮すべき\r
362         if (mainKeyboard.c < KEYBUFSIZ) {\r
363                 mainKeyboard.buf[mainKeyboard.w] = i;\r
364                 mainKeyboard.c++;\r
365                 mainKeyboard.w = (mainKeyboard.w + 1) & (KEYBUFSIZ - 1);\r
366         }\r
367         return;\r
368 }\r
369 \r