view os9/makerom.c @ 11:ce7323f9b937

fix
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 06 Jul 2018 18:31:38 +0900
parents 2a1338b218bf
children 111e5defb8ab
line wrap: on
line source

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

         Shinji KONO    Fri Jul  6 13:31:52 JST 2018

*/

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

// #define DEBUG 1

/*
 * Level1
 *        os9p1 should be 0xf800
 *        it searches ram from the beginning
 *        rom modules are searched from just after the end of RAM
 *
 * Level2
 *        Coco 512kb memory space
 *        last 8k is a ROM (can be switched?) ( block 0x3f )
 *        os9p1 search module on 0x0d00~0x1e00 at block 0x3f
 *
 *        8k block ( offset 0xc000 )
 *
 *        0xe000 - 0xccff   0xff
 *        0xed00 - 0xff78   os9 modules,  os9p1 should be the last
 *                 MMU doesnot touch below
 *        0xff80 - 0xffdf   IO port  ( ACIA, clock, pdisk, MMU )
 *        0xffd0 - 0xffef   boot code
 *        0xfff0 - 0xffff   intr vector
 *         ... next few blocks as extended ROM
 *
 */

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

#define LV2START 0xffd0

// #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);
}

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

void rewrite_vector(MPTR m,int top, unsigned char *adr,int count)
{
    // vector is a offset from $F100 (possibly os9p1 module address)
    int offset = 0xf100-top;
    for(int i=0;i<count;i++) {
        int vec = getword(adr);
        vec -= offset;
        adr[0] = vec>>8;
        adr[1] = vec&0xff;
        adr += 2;
    }
}

// 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);
          rewrite_vector(m,top,m->mod+getword(m->mod+2),7);
       }
   }
   if (level==1 && !(( top+m->size < IOBASE )  || ( IOBASE+IOSIZE < top)) ) {
      top = IOBASE-m->size-1;
      m->ioflag = 1;
#ifdef DEBUG
      printf("*");
#endif 
   } else if (level==2 &&  0xed00 > top) {
      m->ioflag = 1;
   }
   m->location = top;
#ifdef DEBUG
    printf("mod ");
    printOs9Str(m->name);
    printf(" \t: 0x%x - 0x%x\n",top, top + m->size);
#endif 
   return top;
}

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");

 if (level==2) {
     for(int i=0; i<0xd00; i++) fputc(0xff,romfile);
     pos = 0xed00;
 } else {
     pos = start;
 }
 struct os9module *os9p1 = 0;
 for(struct os9module *cur = root.next; cur ; cur = cur->next ) {
    if ( level==2 && cur->ioflag ==1) continue; 
    // 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 (level==1 && 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<LV2START; 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 - 18;
     fputword(vec,romfile);
     fputword(vec+3,romfile);
     fputword(vec+6,romfile);

     fputword(vec+9,romfile);
     fputword(vec+12,romfile);
     fputword(vec+15,romfile);
     fputword(LV2START,romfile);

     pos = 0x10000;
     for(struct os9module *cur = root.next; cur ; cur = cur->next ) {
        if ( cur->ioflag ==0) continue; 
        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;
     }
     while(pos++ & 0x1fff) fputc(0xff,romfile);
 }
 if (level==1) 
     printf("boot rom from 0x%lx\n",0x10000-ftell(romfile)); 
 else
     printf("boot rom from 0xc000 size 0x%lx\n",ftell(romfile)); 
 fclose(romfile);
 return 0;
}