-
Notifications
You must be signed in to change notification settings - Fork 4
/
main.c
153 lines (146 loc) · 4 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
Commandline parsing and general setup
*/
/*
SPDX-License-Identifier: MIT
Copyright (c) 2024 Sprite_tm <[email protected]>
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include "emu.h"
#include "log.h"
#include "emscripten_env.h"
//Strings defining the various log modules
const char *log_str[]={
[LOG_SRC_UART]="uart",
[LOG_SRC_CSR]="csr",
[LOG_SRC_MBUS]="mbus",
[LOG_SRC_MAPPER]="mapper",
[LOG_SRC_SCSI]="scsi",
[LOG_SRC_RAMROM]="ramrom",
[LOG_SRC_RTC]="rtc",
[LOG_SRC_EMU]="emu",
[LOG_SRC_STRACE]="strace",
};
//Strings defining the various log levels.
const char *level_str[]={
"err", "warn", "notice", "info", "debug"
};
//Returns the log level id for a given string in level_str
int loglevel_for(const char *str) {
for (int i=0; i<LOG_LVL_MAX; i++) {
if (strcmp(str, level_str[i])==0) {
return i;
}
}
return -1;
}
//parses either e.g. 'notice' to set all srcs to that,
//or e.g. 'rtc=notice' to only set that source to the level.
//return 1 on error, 0 on ok
int parse_loglvl_str(char *str) {
char *s=strchr(str, '=');
if (!s) s=strchr(str, ':'); //cause I keep mistyping emu:debug instead of emu=debug
if (!s) {
int lvl=loglevel_for(str);
if (lvl==-1) return 1;
for (int i=0; i<LOG_SRC_MAX; i++) {
log_set_level(i, lvl);
}
return 0;
} else {
int lvl=loglevel_for(s+1);
if (lvl==-1) return 1;
for (int i=0; i<LOG_SRC_MAX; i++) {
if (strlen(log_str[i])==(s-str) && strncmp(str, log_str[i], s-str)==0) {
log_set_level(i, lvl);
return 0;
}
}
}
return 1;
}
int main(int argc, char **argv) {
static_assert(sizeof(log_str)/sizeof(log_str[0])==LOG_SRC_MAX,
"log_str array out of sync");
static_assert(sizeof(level_str)/sizeof(level_str[0])==LOG_LVL_MAX,
"level_str array out of sync");
emu_cfg_t cfg={
.u15_rom="U15-MERGED.BIN",
.u17_rom="U17-MERGED.BIN",
#ifdef __EMSCRIPTEN__
.cow_dir="persist/cow",
.rtcram="persist/rtcram.bin",
.realtime=1,
#else
.rtcram="rtcram.bin",
#endif
.hd0img="plexus-sanitized.img",
.mem_size_bytes=2*1024*1024
};
#ifdef __EMSCRIPTEN__
emscripten_init();
#endif
//Parse commandline args
int error=0;
for (int i=1; i<argc; i++) {
if (strcmp(argv[i], "-u15")==0 && i+1<argc) {
i++;
cfg.u15_rom=argv[i];
} else if (strcmp(argv[i], "-u17")==0 && i+1<argc) {
i++;
cfg.u17_rom=argv[i];
} else if (strcmp(argv[i], "-hd")==0 && i+1<argc) {
i++;
cfg.hd0img=argv[i];
} else if (strcmp(argv[i], "-r")==0) {
cfg.realtime=1;
} else if (strcmp(argv[i], "-y")==0) {
cfg.noyolo=1;
} else if (strcmp(argv[i], "-t")==0) {
cfg.tracesyscalls=1;
} else if (strcmp(argv[i], "-l")==0 && i+1<argc) {
i++;
error=parse_loglvl_str(argv[i]);
} else if (strcmp(argv[i], "-c")==0 && i+1<argc) {
i++;
cfg.cow_dir=argv[i];
} else if (strcmp(argv[i], "-m")==0 && i+1<argc) {
i++;
cfg.mem_size_bytes=atoi(argv[i])*1024*1024;
} else {
printf("Unknown argument %s\n", argv[i]);
error=1;
}
if (error) break;
}
int m=cfg.mem_size_bytes/(1024*1024);
if ((m & (m-1)) || m<1 || m>8) {
printf("Memory needs to be 1, 2, 4 or 8MiB (%d given)\n", m);
printf("Note 1 and 8 MB may not be supported by the OS\n");
error=1;
}
if (error) {
printf("Plexus-20 emulator\n");
printf("Usage: %s [args]\n", argv[0]);
printf(" -u15 Path to U15 rom file\n");
printf(" -u17 Path to U17 rom file\n");
printf(" -hd Path to hdimage file\n");
printf(" -r Try to run at realtime speed\n");
printf(" -m n Set the amount of memory to n megabytes\n");
printf(" -l module=level - set logging level of module to specified level\n");
printf(" -l level - Set overal log level to specified level\n");
printf(" -y Disable 'yolo-hack' making the first 8 bytes of ram writable in sys mode\n");
printf(" -t Use traps to trace SysV syscalls\n");
printf("Modules: ");
for (int i=0; i<LOG_SRC_MAX; i++) printf("%s ", log_str[i]);
printf("\n");
printf("Levels: ");
for (int i=0; i<LOG_LVL_MAX; i++) printf("%s ", level_str[i]);
printf("\n");
exit(0);
}
emu_start(&cfg);
}