Mercurial > hg > Members > kono > os9 > sbc09
annotate os9/makerom.c @ 15:bb6a2a9f59f1
boot ...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sat, 07 Jul 2018 19:57:39 +0900 |
parents | 111e5defb8ab |
children | 67046a9431a0 |
rev | line source |
---|---|
0 | 1 /* makerom.c |
2 build ROM image file os9.rom from module list | |
11 | 3 |
4 Shinji KONO Fri Jul 6 13:31:52 JST 2018 | |
5 | |
0 | 6 */ |
7 | |
8 #include <stdio.h> | |
9 #include <stdlib.h> | |
10 #include <strings.h> | |
11 #include <sys/stat.h> | |
12 | |
11 | 13 // #define DEBUG 1 |
14 | |
15 /* | |
16 * Level1 | |
17 * os9p1 should be 0xf800 | |
18 * it searches ram from the beginning | |
19 * rom modules are searched from just after the end of RAM | |
20 * | |
21 * Level2 | |
22 * Coco 512kb memory space | |
23 * last 8k is a ROM (can be switched?) ( block 0x3f ) | |
24 * os9p1 search module on 0x0d00~0x1e00 at block 0x3f | |
25 * | |
26 * 8k block ( offset 0xc000 ) | |
27 * | |
28 * 0xe000 - 0xccff 0xff | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
29 * 0xed00 - 0xfeff os9 modules, os9p1 should be the last |
11 | 30 * MMU doesnot touch below |
31 * 0xff80 - 0xffdf IO port ( ACIA, clock, pdisk, MMU ) | |
32 * 0xffd0 - 0xffef boot code | |
33 * 0xfff0 - 0xffff intr vector | |
34 * ... next few blocks as extended ROM | |
35 * | |
36 */ | |
37 | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
38 int level = 1; |
6 | 39 int IOBASE = 0xe000; |
40 int IOSIZE = 0x100; | |
41 char * outfile ; | |
0 | 42 |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
43 #define LV2START 0xffd0 // our own small boot for mmu |
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
44 #define LV2ROMEND 0xff00 |
9 | 45 |
8 | 46 // #define DEBUG |
47 | |
0 | 48 typedef struct os9module { |
49 int size; | |
50 int location; | |
51 int ioflag; | |
52 unsigned char *mod; | |
53 char *name; | |
54 struct os9module *next; | |
55 } *MPTR ; | |
56 | |
57 struct os9module * | |
58 readOS9module(char *filename) | |
59 { | |
60 FILE *fp = fopen(filename,"rb"); | |
61 if (fp==0) { | |
62 fprintf(stderr,"cannot read %s\n",filename); | |
63 exit(1); | |
64 } | |
65 struct stat st; | |
66 fstat(fileno(fp),&st); | |
67 int size = st.st_size; | |
68 struct os9module *m = malloc(size + sizeof(struct os9module)); | |
69 m->size = size; | |
70 m->next = 0; | |
71 m->ioflag = 0; | |
72 m->mod = (unsigned char*)m + sizeof(struct os9module); | |
73 fread(m->mod , size, 1, fp); | |
74 m->name = (char*) (m->mod + (m->mod[4]*256 + m->mod[5]) ); | |
75 fclose(fp); | |
76 return m; | |
77 } | |
78 | |
79 void | |
80 fputword(unsigned short x, FILE *fp) | |
81 { | |
82 fputc((x>>8)&0xff,fp); | |
83 fputc(x&0xff,fp); | |
84 } | |
85 | |
86 void printOs9Str(char *p) | |
87 { | |
88 while((*p & 0x80)==0) { | |
89 putchar(*p); | |
90 p++; | |
91 } | |
92 putchar(*p & 0x7f); | |
93 } | |
94 | |
10 | 95 unsigned short |
96 getword(unsigned char *ptr) | |
97 { | |
98 return (ptr[0]<<8)+ptr[1]; | |
99 } | |
100 | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
101 void rewrite_vector(MPTR m,int size, unsigned char *adr,int count) |
10 | 102 { |
103 // vector is a offset from $F100 (possibly os9p1 module address) | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
104 int offset = -size-0xf100; |
10 | 105 for(int i=0;i<count;i++) { |
106 int vec = getword(adr); | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
107 vec += offset; |
10 | 108 adr[0] = vec>>8; |
109 adr[1] = vec&0xff; | |
110 adr += 2; | |
111 } | |
112 } | |
113 | |
1 | 114 // calcurate position from the botton |
115 // avoid v09 IO map on 0xe000-0xe800 | |
116 // os9p1 have to be last and at 0xf800 | |
0 | 117 int findLocation(MPTR m, int loc) { |
118 if (m==0) return loc; | |
119 int top = findLocation(m->next, loc) - m->size; | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
120 if (m->next==0) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
121 if (level == 1) |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
122 top = 0xf800; // OS9p1 |
10 | 123 else { |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
124 top = 0x10000-(m->size+0x100); |
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
125 rewrite_vector(m,m->size,m->mod+getword(m->mod+2),7); |
10 | 126 } |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
127 } |
8 | 128 if (level==1 && !(( top+m->size < IOBASE ) || ( IOBASE+IOSIZE < top)) ) { |
0 | 129 top = IOBASE-m->size-1; |
130 m->ioflag = 1; | |
8 | 131 #ifdef DEBUG |
132 printf("*"); | |
133 #endif | |
11 | 134 } else if (level==2 && 0xed00 > top) { |
135 m->ioflag = 1; | |
0 | 136 } |
137 m->location = top; | |
8 | 138 #ifdef DEBUG |
139 printf("mod "); | |
140 printOs9Str(m->name); | |
141 printf(" \t: 0x%x - 0x%x\n",top, top + m->size); | |
142 #endif | |
0 | 143 return top; |
144 } | |
145 | |
146 int | |
147 main(int ac, char *av[]) | |
148 { | |
149 int vectable = 0; | |
150 struct os9module *m = 0, root ; | |
151 root.size = 0; | |
152 root.mod = 0; | |
153 m = &root; | |
154 | |
6 | 155 for(int i = 1 ; i<ac ; i++ ) { |
156 if (*av[i]=='-') { | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
157 if (av[i][1] =='2') { // for level 2 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
158 level = 2; |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
159 IOBASE = LV2ROMEND; |
6 | 160 } else if (av[i][1] =='o') { |
161 outfile = av[i+1]; | |
162 i += 1; | |
163 } else { | |
164 return 1; | |
165 } | |
166 continue; | |
167 } | |
0 | 168 struct os9module *cur; |
169 cur = readOS9module(av[i]); | |
170 m->next = cur; | |
171 m = cur; | |
172 } | |
173 | |
174 FILE *romfile; | |
175 unsigned pos; | |
6 | 176 if (outfile==0) return 1; |
0 | 177 |
6 | 178 romfile=fopen(outfile,"wb"); |
0 | 179 if(!romfile) { |
180 fprintf(stderr,"Cannot create file %s\n",av[1]); | |
181 exit(1); | |
182 } | |
183 | |
184 | |
185 int start = findLocation(root.next,0); | |
186 start = start&0xf800; | |
187 printf("\n\n"); | |
188 | |
11 | 189 if (level==2) { |
190 for(int i=0; i<0xd00; i++) fputc(0xff,romfile); | |
191 pos = 0xed00; | |
192 } else { | |
193 pos = start; | |
194 } | |
8 | 195 struct os9module *os9p1 = 0; |
0 | 196 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { |
11 | 197 if ( level==2 && cur->ioflag ==1) continue; |
6 | 198 // last module have to os9p1 |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
199 if ( cur->next == 0 ) { |
8 | 200 os9p1 = cur; |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
201 if ( level==1 ) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
202 for(; pos < 0xf800 ; pos++) { // os9p1 begins at 0xf800 |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
203 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
204 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
205 } else { |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
206 int pend = 0x10000-( cur->size +0x100); |
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
207 for(; pos < pend ; pos++) { // os9p1 ends 0xfeff |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
208 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
209 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
210 } |
0 | 211 } |
212 printf("mod "); | |
213 printOs9Str(cur->name); | |
214 fwrite(cur->mod, cur->size, 1, romfile); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
215 printf(" \t: 0x%x - 0x%x\n",pos, pos + cur->size-1); |
8 | 216 #ifdef DEBUG |
217 printf(" \t: 0x%x \n",cur->location); | |
218 printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start); | |
219 #endif | |
0 | 220 pos = pos+cur->size; |
11 | 221 if (level==1 && cur->ioflag) { |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
222 if (level==1) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
223 for(; pos < IOBASE + IOSIZE; pos++) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
224 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
225 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
226 printf("*"); |
8 | 227 } |
0 | 228 } |
229 } | |
230 printf("os9 end %x\n",pos); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
231 if (level==1) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
232 vectable = 0x10000 - 2*7; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
233 for( ; pos<vectable; pos++) fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
234 printf("vectbl %x\n",pos); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
235 fputword(0xF82d,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
236 fputword(0xF831,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
237 fputword(0xF835,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
238 fputword(0xF839,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
239 fputword(0xF83d,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
240 fputword(0xF841,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
241 fputword(0xF876,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
242 } else { |
8 | 243 char vector[] = "level2/vector"; |
244 FILE *fp = fopen(vector,"rb"); | |
245 if (fp==0) { | |
246 fprintf(stderr,"cannot read %s\n",vector); | |
247 exit(1); | |
248 } | |
9 | 249 for( ; pos<LV2START; pos++) fputc(0xff,romfile); |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
250 printf("vectbl %x\n",pos); |
8 | 251 for( ; pos<0xfff0; pos++) fputc(fgetc(fp),romfile); |
252 | |
253 #ifdef DEBUG | |
254 printf("os9entry %x\n",os9p1->location); | |
255 #endif | |
256 printf("os9entry %x\n",os9p1->location+getword(os9p1->mod+9)); | |
257 | |
258 fputword(os9p1->location+getword(os9p1->mod+9),romfile); // os9p1 entry point | |
11 | 259 unsigned short vec = os9p1->location+os9p1->size - 18; |
8 | 260 fputword(vec,romfile); |
261 fputword(vec+3,romfile); | |
262 fputword(vec+6,romfile); | |
263 | |
264 fputword(vec+9,romfile); | |
265 fputword(vec+12,romfile); | |
266 fputword(vec+15,romfile); | |
9 | 267 fputword(LV2START,romfile); |
11 | 268 |
269 pos = 0x10000; | |
15 | 270 int bootsize = 2; |
271 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { | |
272 if ( cur->ioflag ==0) continue; | |
273 bootsize += cur->size; | |
274 } | |
275 fputc(bootsize>>8,romfile); | |
276 fputc(bootsize&0xff,romfile); | |
277 pos += 2; | |
11 | 278 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { |
279 if ( cur->ioflag ==0) continue; | |
280 printf("mod "); | |
281 printOs9Str(cur->name); | |
282 fwrite(cur->mod, cur->size, 1, romfile); | |
283 printf(" \t: 0x%x - 0x%x\n",pos, pos + cur->size-1); | |
284 #ifdef DEBUG | |
285 printf(" \t: 0x%x \n",cur->location); | |
286 printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start); | |
287 #endif | |
15 | 288 pos += cur->size; |
11 | 289 } |
290 while(pos++ & 0x1fff) fputc(0xff,romfile); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
291 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
292 if (level==1) |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
293 printf("boot rom from 0x%lx\n",0x10000-ftell(romfile)); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
294 else |
11 | 295 printf("boot rom from 0xc000 size 0x%lx\n",ftell(romfile)); |
0 | 296 fclose(romfile); |
297 return 0; | |
298 } | |
11 | 299 |
300 |