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