Mercurial > hg > Members > kono > os9 > sbc09
annotate os9/makerom.c @ 34:2032755628dc
fix for nitros9
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 15 Jul 2018 14:18:19 +0900 |
parents | 7c5379eb406e |
children |
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 |
17 | 44 #define LV2ROMEND 0xff80 |
9 | 45 |
8 | 46 // #define DEBUG |
47 | |
0 | 48 typedef struct os9module { |
49 int size; | |
34 | 50 int entry; |
0 | 51 int location; |
52 int ioflag; | |
53 unsigned char *mod; | |
54 char *name; | |
55 struct os9module *next; | |
56 } *MPTR ; | |
57 | |
33 | 58 unsigned short vec[8]; |
59 | |
0 | 60 struct os9module * |
61 readOS9module(char *filename) | |
62 { | |
63 FILE *fp = fopen(filename,"rb"); | |
64 if (fp==0) { | |
65 fprintf(stderr,"cannot read %s\n",filename); | |
66 exit(1); | |
67 } | |
68 struct stat st; | |
69 fstat(fileno(fp),&st); | |
70 int size = st.st_size; | |
71 struct os9module *m = malloc(size + sizeof(struct os9module)); | |
72 m->size = size; | |
73 m->next = 0; | |
74 m->ioflag = 0; | |
75 m->mod = (unsigned char*)m + sizeof(struct os9module); | |
76 fread(m->mod , size, 1, fp); | |
77 m->name = (char*) (m->mod + (m->mod[4]*256 + m->mod[5]) ); | |
34 | 78 m->entry = m->mod[9]*256 + m->mod[10] ; |
0 | 79 fclose(fp); |
80 return m; | |
81 } | |
82 | |
83 void | |
84 fputword(unsigned short x, FILE *fp) | |
85 { | |
86 fputc((x>>8)&0xff,fp); | |
87 fputc(x&0xff,fp); | |
88 } | |
89 | |
90 void printOs9Str(char *p) | |
91 { | |
34 | 92 char *q = p; |
0 | 93 while((*p & 0x80)==0) { |
94 putchar(*p); | |
95 p++; | |
96 } | |
97 putchar(*p & 0x7f); | |
34 | 98 while(p<q+8) { |
99 putchar(' '); p++; | |
100 } | |
0 | 101 } |
102 | |
10 | 103 unsigned short |
104 getword(unsigned char *ptr) | |
105 { | |
106 return (ptr[0]<<8)+ptr[1]; | |
107 } | |
108 | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
109 void rewrite_vector(MPTR m,int size, unsigned char *adr,int count) |
10 | 110 { |
111 // 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
|
112 int offset = -size-0xf100; |
10 | 113 for(int i=0;i<count;i++) { |
114 int vec = getword(adr); | |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
115 vec += offset; |
10 | 116 adr[0] = vec>>8; |
117 adr[1] = vec&0xff; | |
118 adr += 2; | |
119 } | |
120 } | |
121 | |
33 | 122 int search_vector(MPTR m) { |
123 unsigned char v[] = { 0x6E, 0x9F, 0x00, 0x2C, 0x6E}; | |
124 for( unsigned char *p = m->mod ; p < m->mod + m->size; p++ ) { | |
125 int i=0; | |
126 for(; i< sizeof(v); i++) { | |
127 if (p[i]!=v[i]) break; | |
128 } | |
129 if (i==sizeof(v)) | |
130 return p - m->mod; | |
131 } | |
132 return 0; | |
133 } | |
134 | |
1 | 135 // calcurate position from the botton |
136 // avoid v09 IO map on 0xe000-0xe800 | |
137 // os9p1 have to be last and at 0xf800 | |
0 | 138 int findLocation(MPTR m, int loc) { |
139 if (m==0) return loc; | |
140 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
|
141 if (m->next==0) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
142 if (level == 1) |
33 | 143 if (m->size > 0xff80-0xf800 ) { |
144 top = 0x10000-(m->size+0x80); | |
145 } else { | |
146 top = 0xf800; // OS9p1 | |
147 } | |
10 | 148 else { |
33 | 149 #if 0 |
150 // old level2 kernel has vector at the bottom | |
17 | 151 top = 0x10000-(m->size+0x80); |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
152 rewrite_vector(m,m->size,m->mod+getword(m->mod+2),7); |
33 | 153 #else |
154 top = 0xf000; // level2 OS9p1 starts here | |
155 // and theses area are RAM /REGISTER STACK/ | |
156 #endif | |
10 | 157 } |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
158 } |
8 | 159 if (level==1 && !(( top+m->size < IOBASE ) || ( IOBASE+IOSIZE < top)) ) { |
0 | 160 top = IOBASE-m->size-1; |
161 m->ioflag = 1; | |
8 | 162 #ifdef DEBUG |
163 printf("*"); | |
164 #endif | |
11 | 165 } else if (level==2 && 0xed00 > top) { |
166 m->ioflag = 1; | |
0 | 167 } |
168 m->location = top; | |
8 | 169 #ifdef DEBUG |
170 printf("mod "); | |
171 printOs9Str(m->name); | |
172 printf(" \t: 0x%x - 0x%x\n",top, top + m->size); | |
173 #endif | |
0 | 174 return top; |
175 } | |
176 | |
177 int | |
178 main(int ac, char *av[]) | |
179 { | |
180 int vectable = 0; | |
181 struct os9module *m = 0, root ; | |
182 root.size = 0; | |
183 root.mod = 0; | |
184 m = &root; | |
185 | |
6 | 186 for(int i = 1 ; i<ac ; i++ ) { |
187 if (*av[i]=='-') { | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
188 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
|
189 level = 2; |
12
111e5defb8ab
boot is called, rti failed
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
11
diff
changeset
|
190 IOBASE = LV2ROMEND; |
6 | 191 } else if (av[i][1] =='o') { |
192 outfile = av[i+1]; | |
193 i += 1; | |
194 } else { | |
195 return 1; | |
196 } | |
197 continue; | |
198 } | |
0 | 199 struct os9module *cur; |
200 cur = readOS9module(av[i]); | |
201 m->next = cur; | |
202 m = cur; | |
203 } | |
204 | |
205 FILE *romfile; | |
206 unsigned pos; | |
6 | 207 if (outfile==0) return 1; |
0 | 208 |
6 | 209 romfile=fopen(outfile,"wb"); |
0 | 210 if(!romfile) { |
211 fprintf(stderr,"Cannot create file %s\n",av[1]); | |
212 exit(1); | |
213 } | |
214 | |
215 | |
216 int start = findLocation(root.next,0); | |
217 start = start&0xf800; | |
218 printf("\n\n"); | |
219 | |
11 | 220 if (level==2) { |
221 for(int i=0; i<0xd00; i++) fputc(0xff,romfile); | |
222 pos = 0xed00; | |
223 } else { | |
224 pos = start; | |
225 } | |
33 | 226 int ofs = 0; |
8 | 227 struct os9module *os9p1 = 0; |
0 | 228 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { |
11 | 229 if ( level==2 && cur->ioflag ==1) continue; |
6 | 230 // last module have to os9p1 |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
231 if ( cur->next == 0 ) { |
8 | 232 os9p1 = cur; |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
233 if ( level==1 ) { |
33 | 234 if (os9p1->size > 0x07f0) { |
235 ofs = (os9p1->size+0xf)&0xfff0; | |
236 ofs -= 0x07f0; | |
237 } | |
238 for(; pos < 0xf800-ofs ; pos++) { // os9p1 begins at 0xf800 | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
239 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
240 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
241 } else { |
33 | 242 #if 0 |
17 | 243 int pend = 0x10000-( cur->size +0x80); |
244 for(; pos < pend ; pos++) { // os9p1 ends 0xff7f | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
245 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
246 } |
33 | 247 #endif |
248 for(; pos < 0xf000 ; pos++) { // level2 os9p1 start from 0xf000 | |
249 fputc(0xff,romfile); | |
250 } | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
251 } |
0 | 252 } |
253 printf("mod "); | |
254 printOs9Str(cur->name); | |
33 | 255 cur->location = pos; |
0 | 256 fwrite(cur->mod, cur->size, 1, romfile); |
34 | 257 printf(" \t: 0x%x - 0x%x size 0x%04x entry 0x%x\n",pos, pos + cur->size-1,cur->size,cur->entry+cur->location); |
8 | 258 #ifdef DEBUG |
259 printf(" \t: 0x%x \n",cur->location); | |
260 printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start); | |
261 #endif | |
0 | 262 pos = pos+cur->size; |
11 | 263 if (level==1 && cur->ioflag) { |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
264 if (level==1) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
265 for(; pos < IOBASE + IOSIZE; pos++) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
266 fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
267 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
268 printf("*"); |
8 | 269 } |
0 | 270 } |
271 } | |
272 printf("os9 end %x\n",pos); | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
273 if (level==1) { |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
274 vectable = 0x10000 - 2*7; |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
275 for( ; pos<vectable; pos++) fputc(0xff,romfile); |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
276 printf("vectbl %x\n",pos); |
33 | 277 if (1) { |
278 int vecofs = search_vector(os9p1); | |
279 if (vecofs==0) { | |
280 printf("can't find vector\n"); | |
281 } | |
34 | 282 static int perm[] = {0,1,5,4,2,3}; |
33 | 283 for(int i=0;i<6;i++) { |
34 | 284 fputword(os9p1->location +vecofs+perm[i]*4,romfile); |
33 | 285 } |
286 int entry_ofs = (m->mod[9]<<8) + m->mod[10]; | |
287 fputword( os9p1->location + entry_ofs ,romfile); | |
288 // printf("os9p1 location ofs %0x\n", os9p1->location); | |
289 // printf("vector ofs %0x\n", vecofs); | |
290 // printf("reset ofs %0x\n", entry_ofs); | |
291 } else { | |
292 fputword(0xF82d-ofs,romfile); | |
293 fputword(0xF831-ofs,romfile); | |
294 fputword(0xF835-ofs,romfile); | |
295 fputword(0xF839-ofs,romfile); | |
296 fputword(0xF83d-ofs,romfile); | |
297 fputword(0xF841-ofs,romfile); | |
298 fputword(0xF876-ofs,romfile); | |
299 } | |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
300 } else { |
8 | 301 char vector[] = "level2/vector"; |
302 FILE *fp = fopen(vector,"rb"); | |
303 if (fp==0) { | |
304 fprintf(stderr,"cannot read %s\n",vector); | |
305 exit(1); | |
306 } | |
9 | 307 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
|
308 printf("vectbl %x\n",pos); |
8 | 309 for( ; pos<0xfff0; pos++) fputc(fgetc(fp),romfile); |
310 #ifdef DEBUG | |
311 printf("os9entry %x\n",os9p1->location); | |
312 #endif | |
313 printf("os9entry %x\n",os9p1->location+getword(os9p1->mod+9)); | |
314 | |
315 fputword(os9p1->location+getword(os9p1->mod+9),romfile); // os9p1 entry point | |
11 | 316 unsigned short vec = os9p1->location+os9p1->size - 18; |
8 | 317 fputword(vec,romfile); |
318 fputword(vec+3,romfile); | |
319 fputword(vec+6,romfile); | |
320 | |
321 fputword(vec+9,romfile); | |
322 fputword(vec+12,romfile); | |
323 fputword(vec+15,romfile); | |
9 | 324 fputword(LV2START,romfile); |
11 | 325 |
326 pos = 0x10000; | |
15 | 327 int bootsize = 2; |
328 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { | |
329 if ( cur->ioflag ==0) continue; | |
330 bootsize += cur->size; | |
331 } | |
332 fputc(bootsize>>8,romfile); | |
333 fputc(bootsize&0xff,romfile); | |
334 pos += 2; | |
11 | 335 for(struct os9module *cur = root.next; cur ; cur = cur->next ) { |
336 if ( cur->ioflag ==0) continue; | |
33 | 337 cur->location = pos; |
11 | 338 printf("mod "); |
339 printOs9Str(cur->name); | |
340 fwrite(cur->mod, cur->size, 1, romfile); | |
34 | 341 printf(" \t: 0x%x - 0x%x size 0x%04x entry 0x%x\n",pos, pos + cur->size-1, cur->size, cur->entry+cur->location); |
11 | 342 #ifdef DEBUG |
343 printf(" \t: 0x%x \n",cur->location); | |
344 printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start); | |
345 #endif | |
15 | 346 pos += cur->size; |
11 | 347 } |
30 | 348 while(pos++ & 0xff) fputc(0xff,romfile); |
7
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
349 } |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
350 if (level==1) |
a6db579d8c11
level 2 rom preparing...
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents:
6
diff
changeset
|
351 printf("boot rom from 0x%lx\n",0x10000-ftell(romfile)); |
30 | 352 else { |
353 long size; | |
354 printf("boot rom from 0xc000 size 0x%lx\n",(size=ftell(romfile))); | |
355 if (size > 0x4d00 + 0x2000) { | |
356 printf(" was too big. make it less than 0x6d00\n"); | |
357 } | |
358 } | |
0 | 359 fclose(romfile); |
360 return 0; | |
361 } | |
11 | 362 |
363 |