view os9/makerom.c @ 8:96a067cf4c4f

level2 rom done
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Thu, 05 Jul 2018 12:07:06 +0900
parents a6db579d8c11
children cb7aa75418b8
line wrap: on
line source

/* makerom.c 
   build ROM image file os9.rom from module list
*/

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/stat.h>

int level = 1;
int IOBASE = 0xe000;
int IOSIZE = 0x100;
char * outfile ;

// #define DEBUG

typedef struct os9module {
   int size;
   int location;
   int ioflag;
   unsigned char *mod;
   char *name;
   struct os9module *next;
} *MPTR ; 

struct os9module *
readOS9module(char *filename) 
{
  FILE *fp = fopen(filename,"rb");
  if (fp==0) {
    fprintf(stderr,"cannot read %s\n",filename);
    exit(1);
  }
  struct stat st;
  fstat(fileno(fp),&st);
  int size = st.st_size;
  struct os9module *m = malloc(size + sizeof(struct os9module));
  m->size = size;
  m->next = 0;
  m->ioflag = 0;
  m->mod = (unsigned char*)m + sizeof(struct os9module);
  fread(m->mod , size, 1, fp);
  m->name = (char*) (m->mod + (m->mod[4]*256 + m->mod[5]) );
  fclose(fp);
  return m;
}

void
fputword(unsigned short x, FILE *fp)
{
   fputc((x>>8)&0xff,fp);
   fputc(x&0xff,fp);
}

void printOs9Str(char *p)
{
   while((*p & 0x80)==0) {
      putchar(*p);
      p++;
   }
   putchar(*p & 0x7f);
}

// calcurate position from the botton
// avoid v09 IO map on 0xe000-0xe800
// os9p1 have to be last and at 0xf800
int findLocation(MPTR m, int loc) {
   if (m==0) return loc;
   int top = findLocation(m->next, loc) - m->size;
   if (m->next==0) {
       if (level == 1)
          top = 0xf800;  // OS9p1
       else
          top = 0x10000-(m->size+0x80);
   }
   if (level==1 && !(( top+m->size < IOBASE )  || ( IOBASE+IOSIZE < top)) ) {
      top = IOBASE-m->size-1;
      m->ioflag = 1;
#ifdef DEBUG
      printf("*");
#endif 
   }
   m->location = top;
#ifdef DEBUG
    printf("mod ");
    printOs9Str(m->name);
    printf(" \t: 0x%x - 0x%x\n",top, top + m->size);
#endif 
   return top;
}

unsigned short
getword(unsigned char *ptr)
{
    return (ptr[0]<<8)+ptr[1];
}

int
main(int ac, char *av[])
{
 int vectable = 0;
 struct os9module *m = 0, root ;
 root.size = 0;
 root.mod = 0;
 m = &root;

 for(int i = 1 ; i<ac ; i++ ) {
    if (*av[i]=='-') {
        if (av[i][1] =='2') {  // for level 2
            level = 2;
            IOBASE = 0xff00;
        } else if (av[i][1] =='o') {
            outfile = av[i+1];
            i += 1;
        } else {
            return 1;
        }
        continue;
    }
    struct os9module *cur;
    cur = readOS9module(av[i]);
    m->next = cur;
    m = cur;
 }

 FILE *romfile;
 unsigned pos;
 if (outfile==0) return 1;

 romfile=fopen(outfile,"wb");
 if(!romfile) {
  fprintf(stderr,"Cannot create file %s\n",av[1]);
  exit(1);
 }

 
 int start = findLocation(root.next,0);
 start = start&0xf800;
 printf("\n\n");

 pos = start;
 struct os9module *os9p1 = 0;
 for(struct os9module *cur = root.next; cur ; cur = cur->next ) {
    // last module have to os9p1
    if ( cur->next == 0 ) {
        os9p1 = cur;
        if ( level==1 ) { 
           for(; pos < 0xf800 ; pos++) {   // os9p1 begins at 0xf800
              fputc(0xff,romfile);
           }
        } else {
           int pend = 0x10000-( cur->size +0x80);
           for(; pos < pend ; pos++) {      // os9p1 ends 0xff7f
              fputc(0xff,romfile);
           }
        }
    }
    printf("mod ");
    printOs9Str(cur->name);
    fwrite(cur->mod, cur->size, 1, romfile);
    printf(" \t: 0x%x - 0x%x\n",pos, pos + cur->size-1);
#ifdef DEBUG
    printf(" \t: 0x%x \n",cur->location);
    printf(" \t: 0x%x - 0x%x : 0x%lx \n",pos, pos + cur->size, ftell(romfile)+start);
#endif 
    pos = pos+cur->size;
    if (cur->ioflag) {
       if (level==1) {
           for(; pos < IOBASE + IOSIZE; pos++) {
              fputc(0xff,romfile);
           }
           printf("*");
       } 
    } 
 }
 printf("os9 end %x\n",pos);
 if (level==1) {
     vectable  = 0x10000 - 2*7;
     for( ; pos<vectable; pos++) fputc(0xff,romfile);
     printf("vectbl %x\n",pos);
     fputword(0xF82d,romfile);
     fputword(0xF831,romfile);
     fputword(0xF835,romfile);
     fputword(0xF839,romfile);
     fputword(0xF83d,romfile);
     fputword(0xF841,romfile);
     fputword(0xF876,romfile);
 } else {
     char vector[] = "level2/vector";
     FILE *fp = fopen(vector,"rb");
     if (fp==0) {
        fprintf(stderr,"cannot read %s\n",vector);
        exit(1);
     }
     for( ; pos<0xffd0; pos++) fputc(0xff,romfile);
     printf("vectbl %x\n",pos);
     for( ; pos<0xfff0; pos++) fputc(fgetc(fp),romfile);

#ifdef DEBUG
     printf("os9entry %x\n",os9p1->location);
#endif 
     printf("os9entry %x\n",os9p1->location+getword(os9p1->mod+9));

     fputword(os9p1->location+getword(os9p1->mod+9),romfile);     // os9p1 entry point 
     unsigned short vec = os9p1->location+os9p1->size + 15;
     fputword(vec,romfile);
     fputword(vec+3,romfile);
     fputword(vec+6,romfile);

     fputword(vec+9,romfile);
     fputword(vec+12,romfile);
     fputword(vec+15,romfile);
     fputword(0xffe0,romfile);
 }
 if (level==1) 
     printf("boot rom from 0x%lx\n",0x10000-ftell(romfile)); 
 else
     printf("boot rom from 0x%lx\n",512*1024-ftell(romfile)); 
 fclose(romfile);
 return 0;
}