OSDN Git Service

MacOSX対応を本家からマージ。
[heavyosecpu/HeavyOSECPU.git] / main.c
1 #include "osecpu.h"
2
3 unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory);
4 void LoadAppBin(HOSECPU_RuntimeEnvironment *env);
5
6 void putKeybuf(int i)
7 {
8         if (keybuf_c < KEYBUFSIZ) {
9                 keybuf[keybuf_w] = i;
10                 keybuf_c++;
11                 keybuf_w = (keybuf_w + 1) & (KEYBUFSIZ - 1);
12         }
13         return;
14 }
15
16 int HeavyOSECPUMain(int argc, char **argv)
17 {
18     FILE *fp;
19     
20     unsigned char *jitbuf, *sysjit00, *sysjit;
21     unsigned char *systmp0, *systmp1, *systmp2;
22     unsigned char *opTbl;
23     HOSECPU_LabelListTag *label;
24     int tmpsiz, i;
25     jmp_buf setjmpEnv;
26         double tm0, tm1, tm2;
27         HOSECPU_PointerControlTag *ptrCtrl;
28     unsigned char *syslib;
29     int argDebug = 0, stacksiz = 1;
30     const  char *cp;
31     HOSECPU_RuntimeEnvironment env;
32         void(*jitfunc)(char *);
33     unsigned char *jp;
34     
35     //実行環境初期化
36     env.mainArgc = argc;
37     env.mainArgv = (const char **)argv;
38     env.appBin = malloc(APPSIZ1);
39     env.executionLevel = JITC_LV_SLOWEST;
40         jitbuf = mallocRWE(1024 * 1024); /* とりあえず1MBで */
41         //unsigned char *sysjit0 = mallocRWE(SJITSIZ1), *sysjit1 = sysjit0, *sysjit00 = sysjit0;
42         // syslib.oseのjitc結果を格納する領域を確保。
43         sysjit00 = mallocRWE(SJITSIZ1);
44         // 現在の、jitc結果を格納するメモリへの書き込み位置のアドレス
45     // sysjit: 現在のjitc書き込み位置
46     // sysjit00: jitc結果の先頭
47         sysjit = sysjit00;
48     //ワークメモリを三つくらいもらう
49         systmp0 = malloc(SYSTMP0SIZ);   /* syslibのjitc用 */
50         systmp1 = malloc(SYSTMP1SIZ);
51         systmp2 = malloc(1024 * 1024);
52     
53     opTbl = malloc(256);
54         label = malloc(JITC_MAXLABELS * sizeof (HOSECPU_LabelListTag));
55         keybuf = malloc(KEYBUFSIZ * sizeof (int));
56         keybuf_r = keybuf_w = keybuf_c = 0;
57         ptrCtrl = malloc(PTRCTRLSIZ * sizeof (HOSECPU_PointerControlTag));
58
59         randStatInit((unsigned int)time(NULL));
60         for (i = 0; i < PTRCTRLSIZ; i++) {
61                 ptrCtrl[i].liveSign = 0;
62                 ptrCtrl[i].size = -1;
63         }
64         ptrCtrl[0].size = -2;
65
66     /* syslibの読み込み */
67     syslib = Init_LoadSysLib(argv[0], systmp0);
68     
69         // jitc.cのerrHndl()をCALLするネィティブコードを挿入。
70         // sysjitの値は次の書き込み位置へずらされる。
71         // 元々のsysjitはsysjit00へ保存されている。
72         sysjit = jitCompInit(sysjit);
73
74         // sysjit (アドレス変数)は下の関数の実行で変更される(だから参照渡し)
75         // もちろんsysjitの値は次の書き込み位置へずらされる。
76         // labelはjitc0()内で初期化される。
77         i = jitc0(&sysjit, sysjit00 + SJITSIZ1, syslib + 32, syslib + SYSLIBSIZ1, JITC_LV_FASTEST, label);
78         if (i != 0){
79                 fputs("syslib-file JITC error.\n", stderr);
80                 return 1;
81         }
82
83         // エラー時にデバッグ用に表示する変数を加算
84         di1_serial++;
85
86     /* アプリバイナリの読み込み */
87     LoadAppBin(&env);
88     
89     /* クロック初期化 */
90         tm0 = clock() / (double)CLOCKS_PER_SEC;
91
92         if (env.appBin[2] == 0xf0) {
93         // tek5圧縮がかかっている
94 #if (USE_TEK5 != 0)
95                 env.appSize1 = tek5Decomp(env.appBin + 2, env.appBin + env.appSize0, systmp0) + 2;
96 #else
97                 env.appSize1 = -9;
98 #endif
99                 if (env.appSize1 < 0) {
100                         fputs("unsupported-format(tek5)\n", stderr);
101                         return 1;
102                 }
103         }
104     //デバッグモード指定
105         cp = searchArg(argc, (const char **)argv, "debug:", 0);
106         if (cp != NULL){
107         argDebug = *cp - '0';
108     }
109     //スタックサイズ指定
110         cp = searchArg(argc, (const char **)argv, "stack:", 0);
111         if (cp != NULL){
112         stacksiz = strtol(cp, NULL, 0);
113     }
114         jp = jitbuf; /* JIT-pointer */
115
116         /* フロントエンドコードをバックエンドコードに変換する */
117         if ((env.appBin[2] & 0xf0) != 0) {
118                 systmp0[0] = env.appBin[0];
119                 systmp0[1] = env.appBin[1];
120                 env.preg[2].p = systmp0 + 2;
121                 env.preg[3].p = systmp0 + SYSTMP0SIZ;
122                 env.preg[4].p = env.appBin + 2;
123                 env.preg[5].p = env.appBin + env.appSize1;
124                 env.preg[6].p = systmp1;
125                 env.preg[7].p = systmp1 + SYSTMP1SIZ;
126                 env.preg[10].p = systmp2;
127                 int pxxFlag[64], typLabel[4096];
128                 env.preg[0x0b].p = (void *)pxxFlag;
129                 env.preg[0x0c].p = (void *)typLabel;
130                 env.preg[0x0d].p = opTbl;
131                 jitfunc = (void *)sysjit;
132                 (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */
133                 if (env.ireg[0] != 0) {
134                         jp = env.preg[2].p - 1;
135                         fprintf(stderr, "unpack error: %02X (at %06X) (R00=%d)\n", *jp, jp - systmp0, env.ireg[0]);
136                         if ((argDebug & 2) != 0) {
137                                 fp = fopen("debug2.bin", "wb");
138                                 fwrite(systmp0, 1, jp - systmp0 + 16, fp);
139                                 fclose(fp);
140                         }
141                         exit(1);
142                 }
143                 tmpsiz = env.preg[2].p - systmp0;
144         } else{
145                 memcpy(systmp0, env.appBin, env.appSize1);
146                 tmpsiz = env.appSize1;
147         }
148
149         if ((argDebug & 2) != 0) {
150                 fp = fopen("debug2.bin", "wb");
151                 fwrite(systmp0, 1, tmpsiz, fp);
152                 fclose(fp);
153         }
154
155         i = jitc0(&jp, jitbuf + 1024 * 1024, systmp0, systmp0 + tmpsiz, env.executionLevel, label);
156         if (i == 1){
157         fputs("app-file header error.\n", stderr);
158                 return 1;
159     }
160         if (i != 0){
161         return 1;
162     }
163         di1_serial++;
164
165         int appsiz2 = jp - jitbuf;
166
167         unsigned char *p28 = jp;
168         jp = jitCompCallFunc(jp, &devFunc);
169
170         tm1 = clock() / (double)CLOCKS_PER_SEC;
171
172         /* レジスタ初期化 */
173         for (i = 0; i < 64; i++){
174                 env.ireg[i] = 0;
175     }
176         for (i = 0; i < 64; i++) {
177                 env.preg[i].p = NULL;
178                 env.preg[i].typ = -1;
179                 env.preg[i].p0 = NULL;
180                 env.preg[i].p1 = NULL;
181         }
182
183         env.argc = argc;
184         env.argv = (const char **)argv;
185         env.buf0 = env.buf1 = NULL;
186         env.preg[0x28].p = p28;
187         env.preg[0x28].typ = 0; // TYP_CODE
188         env.preg[0x28].p0 = p28;
189         env.preg[0x28].p1 = p28 + 1;
190         //      env.preg[0x00].p = malloc(1024 * 1024) + (1024 * 1024 - 32);
191         env.junkStack = malloc(stacksiz << 20);
192         env.junkStack1 = env.junkStack + (stacksiz << 20);
193         env.winClosed = 0;
194         env.autoSleep = 0;
195         env.setjmpEnv = &setjmpEnv;
196         env.lastConsoleChar = '\n';
197
198         env.label = label;
199         env.maxLabels = JITC_MAXLABELS;
200         env.jitbuf = jp;
201         env.jitbuf1 = jitbuf + 1024 * 1024;
202         env.errHndl = &errorHandler;
203         env.dbgr = 0;
204         if (searchArg(argc, (const char **)argv, "dbgr:1", 0) != NULL){
205         env.dbgr = 1;
206     }
207
208         if ((argDebug & 1) != 0) {
209                 fp = fopen("debug1.bin", "wb");
210                 fwrite(jitbuf, 1, jp - jitbuf, fp);
211                 fclose(fp);
212         }
213
214         /* JITコード実行 */
215         jitfunc = (void *)jitbuf;
216         if (setjmp(setjmpEnv) == 0){
217                 (*jitfunc)(((char *)&env) + 128); /* サイズを節約するためにEBPを128バイトずらす */
218     }
219         if (env.autoSleep != 0) {
220                 if (vram != NULL){
221                         drv_flshWin(v_xsiz, v_ysiz, 0, 0);
222         }
223                 while (env.winClosed == 0){
224                         drv_sleep(100);
225         }
226         }
227         if (env.lastConsoleChar != '\n'){
228                 putchar('\n');
229     }
230
231         tm2 = clock() / (double)CLOCKS_PER_SEC;
232
233         /* 実行結果確認のためのレジスタダンプ */
234         if (searchArg(argc, (const char **)argv, "verbose:1", 0) != NULL) {
235                 printf("time: JITC=%.3f[sec], exec=%.3f[sec]\n", tm1 - tm0, tm2 - tm1);
236                 printf("size: OSECPU=%d, decomp=%d, tmp=%d, native=%d\n", env.appSize0, env.appSize1, tmpsiz, appsiz2);
237                 printf("result:\n");
238                 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]);
239         }
240 #if (USE_DEBUGGER != 0)
241         dbgrMain(&env);
242 #endif
243         return 0;
244 }
245
246 unsigned char *Init_LoadSysLib(char argv0[], unsigned char *tmpWorkMemory)
247 {
248     unsigned char *syslib;
249     FILE *fp;
250     unsigned char *up;
251     int appsize;
252     
253     /* syslibの読み込み */
254         syslib = malloc(SYSLIBSIZ1);
255         fp = fopen(SYSLIB_OSE, "rb");
256         if (fp == NULL) {
257                 syslib[0] = '/';
258                 strcpy((char *)syslib + 1, argv0);
259                 up = syslib + 1;
260                 while (*up != '\0'){
261             up++;
262         }
263                 while (*up != '/' && *up != 0x5c){
264             up--;
265         }
266                 up++;
267                 strcpy((char *)up, SYSLIB_OSE);
268                 fp = fopen((char *)syslib + 1, "rb");
269         }
270         if (fp == NULL) {
271                 fputs("syslib-file fopen error.\n", stderr);
272         exit(EXIT_FAILURE);
273         }
274         appsize = fread(syslib, 1, SYSLIBSIZ1 - 4, fp);
275         fclose(fp);
276         if (appsize >= SYSLIBSIZ1 - 4) {
277                 fputs("syslib-file too large.\n", stderr);
278                 exit(EXIT_FAILURE);
279         }
280         if (syslib[0] == 0x05 && syslib[1] == 0xc1) {
281                 // 一体この部分ではなにをやっているのだろう?
282                 // OSECPUに0x05, 0x1bという命令はないが... ヘッダ?
283                 // どうせ初めからの32バイトは無視されるのだろうに...
284                 memcpy(tmpWorkMemory, syslib, appsize);
285                 ComLib_main(tmpWorkMemory + 2, syslib + 2);
286                 syslib[0] = 0x05;
287                 syslib[1] = 0x1b;
288         }
289     
290         fp = fopen("syslib_dbg.ose", "wb");
291         fwrite(syslib, 1, SYSLIBSIZ1, fp);
292         fclose(fp);
293     return syslib;
294 }
295
296 void LoadAppBin(HOSECPU_RuntimeEnvironment *env)
297 {
298     FILE *fp;
299     const char *fileName;
300         /* アプリバイナリの読み込み */
301         if (env->mainArgc <= 1) {
302         //アプリ名未指定なので何事もなく終了
303         exit(EXIT_SUCCESS);
304     }
305         fileName = env->mainArgv[1];
306     //アプリ名先頭に:n:をつけることでレベルnでの実行が可能?
307         if (fileName[0] == ':' && fileName[2] == ':') {
308                 env->executionLevel = fileName[1] - '0';
309                 if (env->executionLevel < 0 || env->executionLevel > 9){
310                         env->executionLevel = JITC_LV_SLOWEST;
311         }
312                 fileName += 3;
313         }
314     
315         fp = fopen(fileName, "rb");
316         if (fp == NULL) {
317                 fputs("app-file load error.\n", stderr);
318                 exit(EXIT_FAILURE);
319         }
320         env->appSize0 = fread(env->appBin, 1, APPSIZ1 - 4, fp);
321     env->appSize1 = env->appSize0;
322         fclose(fp);
323     
324         if (env->appSize0 >= APPSIZ1 - 4) {
325                 fputs("app-file too large.\n", stderr);
326                 exit(EXIT_FAILURE);
327         }
328         if (env->appSize0 < 3) {
329                 fputs("app-file header error.\n", stderr);
330                 exit(EXIT_FAILURE);
331         }
332 }