home *** CD-ROM | disk | FTP | other *** search
/ 64'er / 64ER_CD.iso / spec_emu / spconv / spconv.c < prev    next >
C/C++ Source or Header  |  1992-12-13  |  24KB  |  1,346 lines

  1. #include <stdio.h>
  2. #include <fcntl.h>
  3. #include <sys/stat.h>
  4. #include <string.h>
  5. #include <alloc.h>
  6.  
  7. void read_image(char * s);
  8. void write_image(char * s);
  9. void read_jpp(char * s);
  10. void write_jpp(char * s);
  11. void read_vgaspec_header(char * s);
  12. void read_vgaspec(char * s);
  13. void write_vgaspec(char * s);
  14. void read_old_vgaspec(char * s);
  15. void write_old_vgaspec(char * s);
  16. void read_raw(char * s);
  17. void read_z80(char * s);
  18. void write_z80(char * s);
  19. void read_prg(char * s);
  20. void write_prg(char * s);
  21. void jpp_to_vgaspec();
  22. void vgaspec_to_jpp();
  23. void raw_to_jpp();
  24. void jpp_to_z80();
  25. void z80_to_jpp();
  26. void jpp_to_prg();
  27. void prg_to_jpp();
  28. void z80_uncompress();
  29. void z80_uncompress();
  30. int  z80_compress();
  31.  
  32. union header_u {
  33.     char in[9];
  34.     struct {
  35.         char type;
  36.         unsigned int  length;
  37.         unsigned int  start;
  38.         char var;
  39.         char res1;
  40.         int  line;
  41.     } header;
  42. } h;
  43.  
  44. char expect[]={
  45.     0x03,        /* type CODE */
  46.     0x00,0xc0,    /* image size */
  47.     0x00,0x40,    /* image start */
  48.     0xff,        /* var */
  49.     0xff,        /* res1 */
  50.     0xff,0xff    /* line */
  51. };    
  52.  
  53. struct jpp_s {
  54.     unsigned char i;
  55.     unsigned char lax;
  56.     unsigned char hax;
  57.     unsigned char eax;
  58.     unsigned char dax;
  59.     unsigned char cax;
  60.     unsigned char bax;
  61.     unsigned char fax;
  62.     unsigned char aax;
  63.     unsigned char l;
  64.     unsigned char h;
  65.     unsigned char e;
  66.     unsigned char d;
  67.     unsigned char c;
  68.     unsigned char b;
  69.     unsigned char iyl;
  70.     unsigned char iyh;
  71.     unsigned char ixl;
  72.     unsigned char ixh;
  73.     unsigned char iff2;
  74.     unsigned char r;
  75.     unsigned char f;
  76.     unsigned char a;
  77.     unsigned char spl;
  78.     unsigned char sph;
  79.     unsigned char im;
  80.     unsigned char border;
  81. } jpp;
  82.  
  83. struct vga_s {
  84. /*00*/    unsigned char S;
  85. /*01*/    unsigned char P;
  86. /*02*/    unsigned int len;
  87. /*04*/    unsigned int start;
  88. /*06*/    unsigned char c;
  89. /*07*/    unsigned char b;
  90. /*08*/    unsigned char e;
  91. /*09*/    unsigned char d;
  92. /*0A*/    unsigned char l;
  93. /*0B*/    unsigned char h;
  94. /*0C*/    unsigned char f;
  95. /*0D*/    unsigned char a;
  96. /*0E*/    unsigned char ixl;
  97. /*0F*/    unsigned char ixh;
  98. /*10*/    unsigned char iyl;
  99. /*11*/    unsigned char iyh;
  100. /*12*/    unsigned char cax;
  101. /*13*/    unsigned char bax;
  102. /*14*/    unsigned char eax;
  103. /*15*/    unsigned char dax;
  104. /*16*/    unsigned char lax;
  105. /*17*/    unsigned char hax;
  106. /*18*/    unsigned char fax;
  107. /*19*/    unsigned char aax;
  108. /*1A*/    unsigned char r;
  109. /*1B*/    unsigned char i;
  110. /*1C*/    unsigned char spl;
  111. /*1D*/    unsigned char sph;
  112. /*1E*/    unsigned char pcl;
  113. /*1F*/    unsigned char pch;
  114. /*20*/    unsigned char res2;
  115. /*21*/    unsigned char res3;
  116. /*22*/    unsigned char border;
  117. /*23*/    unsigned char res4;
  118. /*24*/    unsigned char im;
  119. /*25*/    unsigned char res5;
  120. } vga;
  121.  
  122. struct z80_s {
  123. /*00*/    unsigned char a;
  124. /*01*/    unsigned char f;
  125. /*02*/    unsigned char c;
  126. /*03*/    unsigned char b;
  127. /*04*/    unsigned char l;
  128. /*05*/    unsigned char h;
  129. /*06*/    unsigned char pcl;
  130. /*07*/    unsigned char pch;
  131. /*08*/    unsigned char spl;
  132. /*09*/    unsigned char sph;
  133. /*0A*/    unsigned char i;
  134. /*0B*/    unsigned char r;
  135. /*0C*/    unsigned char data;
  136. /*0D*/    unsigned char e;
  137. /*0E*/    unsigned char d;
  138. /*0F*/    unsigned char cax;
  139. /*10*/    unsigned char bax;
  140. /*11*/    unsigned char eax;
  141. /*12*/    unsigned char dax;
  142. /*13*/    unsigned char lax;
  143. /*14*/    unsigned char hax;
  144. /*15*/    unsigned char aax;
  145. /*16*/    unsigned char fax;
  146. /*17*/    unsigned char iyl;
  147. /*18*/    unsigned char iyh;
  148. /*19*/    unsigned char ixl;
  149. /*1A*/    unsigned char ixh;
  150. /*1B*/    unsigned char iff1;
  151. /*1C*/    unsigned char iff2;
  152. /*1D*/    unsigned char im;
  153. } z80;
  154.  
  155. struct prg_s {
  156. /*00*/    char name[10];
  157. /*0A*/    char nullbyte;
  158. /*0B*/    unsigned char contains_0x61;
  159. /*0C*/    unsigned char contains_0x35;
  160. /*0D*/    unsigned char contains_0x03;
  161. /*0E*/  unsigned char contains_0x00[0xdc-0x0e];
  162. /*DC*/    unsigned char iyl;
  163. /*DD*/    unsigned char iyh;
  164. /*DE*/    unsigned char ixl;
  165. /*DF*/    unsigned char ixh;
  166. /*E0*/    unsigned char eax;
  167. /*E1*/    unsigned char dax;
  168. /*E2*/    unsigned char cax;
  169. /*E3*/    unsigned char bax;
  170. /*E4*/    unsigned char lax;
  171. /*E5*/    unsigned char hax;
  172. /*E6*/    unsigned char fax;
  173. /*E7*/    unsigned char aax;
  174. /*E8*/    unsigned char e;
  175. /*E9*/    unsigned char d;
  176. /*EA*/    unsigned char c;
  177. /*EB*/    unsigned char b;
  178. /*EC*/    unsigned char l;
  179. /*ED*/    unsigned char h;
  180. /*EE*/    unsigned char iff2;
  181. /*EF*/    unsigned char i;
  182. /*F0*/    unsigned char spl;
  183. /*F1*/    unsigned char sph;
  184. /*F2*/    unsigned char filler[0x0e];
  185. } prg;
  186.  
  187. #define IMSIZE 49152
  188.  
  189. unsigned char image[IMSIZE];
  190.  
  191. unsigned int z80_size;
  192.  
  193. int    intype;
  194. int    outtype;
  195.  
  196. #define    RAW        1
  197. #define JPP        2
  198. #define    SPECTRUM    3
  199. #define    Z80        4
  200. #define    PRG        5
  201. #define    UNKNOWN        6
  202.  
  203. unsigned int addr;
  204. unsigned int sp;
  205. unsigned int pc;
  206. int fd;
  207.  
  208. main(argc,argv)
  209. int argc;
  210. char *argv[];
  211. {
  212.     int i;
  213.     char *p;
  214.     struct stat status;
  215.     char * fromstring;
  216.     char * tostring;
  217.     char * outfile;
  218.  
  219.     if(argc != 3)
  220.     {
  221.         fprintf(stderr,"SPCONV version 1.02 - %s\n\n",__DATE__);
  222.         fprintf(stderr,"Usage: spconv <source> <target>\n\n");
  223.         fprintf(stderr,"Source must be a valid .SNA, .SP, .Z80, .PRG or RAW file.\n");
  224.         fprintf(stderr,"Target must be a .SNA, .SP, .Z80 or .PRG file.\n\n");
  225.         fprintf(stderr,"If the second parameter contains only a suffix, the prefix\n");
  226.         fprintf(stderr,"of the input file will be used (i.e. 'spconv file.sna .z80')\n\n");
  227.         fprintf(stderr,"Output .SP files are in the new format, .Z80 files are compressed.\n\n");
  228.         fprintf(stderr,"If <source> and <target> are .SP files, convertion from old\n");
  229.         fprintf(stderr,"to new format or from new to old format will be performed.\n");
  230.         fprintf(stderr,"If <source> and <target> are of the same type an error message\n");
  231.         fprintf(stderr,"will be generated (unless they are both .SP files)\n");
  232.         fprintf(stderr,"\n\nPublic Domain, H. de Groot 1992\n\n");
  233.  
  234.         return 1;
  235.     }
  236.  
  237.     if((strchr(argv[1],'*')!=NULL) || (strrchr(argv[1],'?')!=NULL) ||
  238.        (strchr(argv[2],'*')!=NULL) || (strrchr(argv[2],'?')!=NULL))
  239.     {
  240.         fprintf(stderr,"This program can't handle wildcards, sorry!\n");
  241.         return 1;
  242.     }
  243.  
  244.     if(stat(argv[1],&status)<0)
  245.     {
  246.         perror(argv[1]);
  247.         return 1;
  248.     }
  249.  
  250.     /* 
  251.      * recognize input type on filename:
  252.      *
  253.      *    .SNA    ->    JPP file
  254.      *    .SP    ->    SPECTRUM file (was VGASPEC)
  255.      *    .Z80    ->    Z80 file
  256.      *    .PRG    ->    PRG file
  257.      *    other    ->    if exact 48+header -> raw file
  258.      *    otherwise     unknown
  259.      */
  260.  
  261.     intype=UNKNOWN;
  262.     p=strrchr(argv[1],'.');
  263.     if(p==NULL) p=argv[1]; /* not found, set at begin of string */
  264.     if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0))
  265.     {
  266.         fromstring="from .SNA";
  267.         intype=JPP;
  268.     }
  269.     if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0)) 
  270.     {
  271.         fromstring="from .Z80";
  272.         intype=Z80;
  273.     }
  274.     if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0)) 
  275.     {
  276.         fromstring="from .SP";
  277.         intype=SPECTRUM;
  278.     }
  279.     if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0)) 
  280.     {
  281.         fromstring="from .PRG";
  282.         intype=PRG;
  283.     }
  284.  
  285.     if(intype==UNKNOWN)
  286.         if (status.st_size == (sizeof(h)+IMSIZE)) 
  287.         {
  288.             fromstring="from RAW";
  289.             intype=RAW;
  290.         }
  291.  
  292.     /* 
  293.      * recognize output type on filename:
  294.      *
  295.      *    .SNA    ->    JPP file
  296.      *    .SP    ->    SPECTRUM file (was VGASPEC)
  297.      *    .Z80    ->    Z80 file
  298.      *    .PRG    ->    PRG file
  299.      *    otherwise     unknown
  300.      */
  301.     outtype=UNKNOWN;
  302.  
  303.     p=strrchr(argv[2],'.');
  304.     if(p==NULL) p=argv[2]; /* not found, set at begin of string */
  305.     if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0)) 
  306.     {
  307.         tostring="to .SNA";
  308.         outtype=JPP;
  309.     }
  310.     if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0)) 
  311.     {
  312.         tostring="to .Z80";
  313.         outtype=Z80;
  314.     }
  315.     if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0)) 
  316.     {
  317.         tostring="to .SP";
  318.         outtype=SPECTRUM;
  319.     }
  320.     if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0)) 
  321.     {
  322.         tostring="to .PRG";
  323.         outtype=PRG;
  324.     }
  325.  
  326.     if(intype==UNKNOWN)
  327.     {
  328.         fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80 or .PRG file,\r");
  329.         fprintf(stderr,"or a Raw file\n");
  330.         return 3;
  331.     }
  332.  
  333.     if(outtype==UNKNOWN)
  334.     {
  335.         fprintf(stderr,"Unknown output file format. Must be a .SNA, .SP or .Z80 or .PRG file\n");
  336.         return 4;
  337.     }
  338.  
  339.     /* 
  340.        if argv[2] only contains the suffix then use the prefix of
  341.        argv[1];
  342.      */
  343.     if(argv[2][0]=='.')
  344.     {
  345.         outfile=malloc(strlen(argv[1])+strlen(argv[2])+1);
  346.         strcpy(outfile,argv[1]); /* copy prefix    */
  347.  
  348.         p=strrchr(outfile,'.');
  349.         if(p!=NULL) *p='\0'; /* put end of string at position of '.' */
  350.  
  351.         strcat(outfile,argv[2]); /* append suffix  */
  352.     }
  353.     else
  354.     {
  355.         outfile=malloc(strlen(argv[2]));
  356.  
  357.         strcpy(outfile,argv[2]);
  358.     }
  359.  
  360.     if(intype==outtype)
  361.     {
  362.         if(intype!=SPECTRUM)
  363.         {
  364.         fprintf(stderr,"Input and output file format are the same. ");
  365.         fprintf(stderr,"What you try to do\n");
  366.         fprintf(stderr,"is handled much better by the MSDOS \"COPY\" ");
  367.         fprintf(stderr,"command!\n");
  368.         return 3;
  369.         }
  370.         else
  371.         {
  372.             if((status.st_size == (sizeof(vga)+IMSIZE)))
  373.             {
  374.                 printf("Converting %s from new .SP format to old .SP format.\n",argv[1]);
  375.                 read_vgaspec(argv[1]);
  376.  
  377.                 write_old_vgaspec(outfile);
  378.                 return 0;
  379.             }
  380.             else if((status.st_size == (sizeof(vga)+IMSIZE-6)))
  381.             {
  382.                 read_vgaspec_header(argv[1]);
  383.                 if((vga.S=='S')&&(vga.P=='P'))
  384.                 {
  385. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  386. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  387. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  388. fprintf(stderr,"contain images of 48Kb length.\n");
  389.                     return 3;
  390.                 }
  391.  
  392.                 printf("Converting %s from old .SP format to new .SP format.\n",argv[1]);
  393.                 read_old_vgaspec(argv[1]);
  394.                 vga.S='S';
  395.                 vga.P='P';
  396.                 vga.len=0xC000;
  397.                 vga.start=0x4000;
  398.                 write_vgaspec(outfile);
  399.                 return 0;
  400.             }
  401.             else
  402.             {
  403.                 read_vgaspec_header(argv[1]);
  404.                 if((vga.S=='S')&&(vga.P=='P'))
  405.                 {
  406. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  407. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  408. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  409. fprintf(stderr,"contain images of 48Kb length.\n");
  410.                     return 3;
  411.                 }
  412.                 else
  413.                 {
  414. fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80 or .PRG file\n");
  415.                     return 3;
  416.                 }
  417.             }
  418.         }
  419.     }
  420.  
  421.     printf("Converting %s %s %s\n",argv[1],fromstring,tostring);
  422.  
  423.     /*
  424.      * convert input_file to JPP
  425.      */
  426.     if((intype==JPP) && (status.st_size == (sizeof(jpp)+IMSIZE)))
  427.     {
  428.         read_jpp(argv[1]);
  429.     }
  430.     else if ((intype==SPECTRUM)&&((status.st_size == (sizeof(vga)+IMSIZE))))
  431.     {
  432.         read_vgaspec(argv[1]);
  433.         
  434.         vgaspec_to_jpp();
  435.     }
  436.     else if ((intype==SPECTRUM)&&((status.st_size == (sizeof(vga)+IMSIZE-6))))
  437.     {
  438.         read_old_vgaspec(argv[1]);
  439.         
  440.         vgaspec_to_jpp();
  441.     }
  442.     else if (intype==RAW)
  443.     {
  444.         read_raw(argv[1]);
  445.  
  446.         raw_to_jpp();
  447.     }
  448.     else if (intype==Z80)
  449.     {
  450.         read_z80(argv[1]);
  451.  
  452.         z80_to_jpp();
  453.     }
  454.     else if (intype==PRG)
  455.     {
  456.         if(status.st_size != (sizeof(prg)+IMSIZE))
  457.         {
  458.             printf("Warning: the image part of %s is not exactly 48k!\n",argv[1]);
  459.             printf("         Converting anyway, the converted file may not work\n");
  460.         }
  461.         read_prg(argv[1]);
  462.  
  463.         prg_to_jpp();
  464.     }
  465.     else
  466.     {
  467.         printf("Unrecognized input file type, can't convert\n");
  468.         return 3;
  469.     }
  470.  
  471.     /*
  472.      * convert internal JPP format to output file
  473.      */
  474.     if(outtype==JPP)
  475.     {
  476.         write_jpp(outfile);
  477.     }
  478.     else if (outtype==SPECTRUM)
  479.     {
  480.         jpp_to_vgaspec();
  481.     
  482.         write_vgaspec(outfile);
  483.     }
  484.     else if (outtype==Z80)
  485.     {
  486.         jpp_to_z80();
  487.  
  488.         write_z80(outfile);
  489.     }
  490.     else if (outtype==PRG)
  491.     {
  492.         jpp_to_prg(outfile);
  493.  
  494.         write_prg(outfile);
  495.     }
  496.     else
  497.     {
  498.         printf("Unrecognized output file type, can't convert\n");
  499.         return 4;
  500.     }
  501.     return 0;
  502. }
  503.  
  504. void read_image(char * s)
  505. {
  506.     if(read(fd,image,IMSIZE)==-1)
  507.     {
  508.         perror(s);
  509.         exit(1);
  510.     }
  511. }
  512.  
  513. void write_image(char * s)
  514. {
  515.     if(write(fd,image,IMSIZE)==-1)
  516.     {
  517.         perror(s);
  518.         exit(2);
  519.     }
  520. }
  521.  
  522. void read_jpp(char * s)
  523. {
  524.     fd=open(s,O_RDONLY|O_BINARY);
  525.     if(fd < 0)
  526.     {
  527.         perror(s);
  528.         exit(1);
  529.     }
  530.     if(read(fd,&jpp,sizeof(jpp))==-1)
  531.     {
  532.         perror(s);
  533.         exit(1);
  534.     }
  535.     read_image(s);
  536.     close(fd);
  537. }
  538.  
  539. void write_jpp(char * s)
  540. {
  541.     unlink(s);
  542.  
  543.     fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
  544.     if(fd<0)
  545.     {
  546.         perror(s);
  547.         exit(2);
  548.     }
  549.         
  550.     if(write(fd,&jpp,sizeof(jpp))==-1)
  551.     {
  552.         perror(s);
  553.         exit(2);
  554.     }
  555.     write_image(s);
  556.     close(fd);
  557. }
  558.  
  559. void read_vgaspec_header(char * s)
  560. {
  561.     fd=open(s,O_RDONLY|O_BINARY);
  562.     if(fd < 0)
  563.     {
  564.         perror(s);
  565.         exit(1);
  566.     }
  567.     if(read(fd,&vga,sizeof(vga))==-1)
  568.     {
  569.         perror(s);
  570.         exit(1);
  571.     }
  572.     close(fd);
  573. }
  574.  
  575. void read_vgaspec(char * s)
  576. {
  577.     fd=open(s,O_RDONLY|O_BINARY);
  578.     if(fd < 0)
  579.     {
  580.         perror(s);
  581.         exit(1);
  582.     }
  583.     if(read(fd,&vga,sizeof(vga))==-1)
  584.     {
  585.         perror(s);
  586.         exit(1);
  587.     }
  588.     read_image(s);
  589.     close(fd);
  590. }
  591.  
  592. void write_vgaspec(char * s)
  593. {
  594.     unlink(s);
  595.  
  596.     fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
  597.     if(fd<0)
  598.     {
  599.         perror(s);
  600.         exit(2);
  601.     }
  602.  
  603.     if(write(fd,&vga,sizeof(vga))==-1)
  604.     {
  605.         perror(s);
  606.         exit(2);
  607.     }
  608.     write_image(s);
  609.     close(fd);
  610. }
  611.  
  612. void read_old_vgaspec(char * s)
  613. {
  614.     fd=open(s,O_RDONLY|O_BINARY);
  615.     if(fd < 0)
  616.     {
  617.         perror(s);
  618.         exit(1);
  619.     }
  620.     if(read(fd,((char *)&vga)+6,sizeof(vga)-6)==-1)
  621.     {
  622.         perror(s);
  623.         exit(1);
  624.     }
  625.     read_image(s);
  626.     close(fd);
  627. }
  628.  
  629. void write_old_vgaspec(char * s)
  630. {
  631.     unlink(s);
  632.  
  633.     fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
  634.     if(fd<0)
  635.     {
  636.         perror(s);
  637.         exit(2);
  638.     }
  639.  
  640.     if(write(fd,((char *)&vga)+6,sizeof(vga)-6)==-1)
  641.     {
  642.         perror(s);
  643.         exit(2);
  644.     }
  645.     write_image(s);
  646.     close(fd);
  647. }
  648.  
  649. void read_raw(char * s)
  650. {
  651.     int i;
  652.  
  653.     fd=open(s,O_RDONLY|O_BINARY);
  654.     if(fd < 0)
  655.     {
  656.         perror(s);
  657.         exit(1);
  658.     }
  659.     if(read(fd,&h,sizeof(h))==-1)
  660.     {
  661.         perror(s);
  662.         exit(1);
  663.     }
  664.     for(i=0;i<9;i++)
  665.     {
  666.         if(h.in[i]!=expect[i])
  667.         {
  668.             fprintf(stderr,"Header of spectum image not ok, ");
  669.             fprintf(stderr,"Spectrum image should be saved with:\n");
  670.             fprintf(stderr,"SAVE *\"b\"CODE 16384,49152");
  671.             exit(1);
  672.         }
  673.     }
  674.     read_image(s);
  675.     close(fd);
  676. }
  677.  
  678. void read_z80(char * s)
  679. {
  680.     fd=open(s,O_RDONLY|O_BINARY);
  681.     if(fd < 0)
  682.     {
  683.         perror(s);
  684.         exit(1);
  685.     }
  686.     if(read(fd,&z80,sizeof(z80))==-1)
  687.     {
  688.         perror(s);
  689.         exit(1);
  690.     }
  691.     read_image(s);
  692.     close(fd);
  693. }
  694.  
  695. void write_z80(char * s)
  696. {
  697.     unlink(s);
  698.  
  699.     fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
  700.     if(fd<0)
  701.     {
  702.         perror(s);
  703.         exit(2);
  704.     }
  705.         
  706.     if(write(fd,&z80,sizeof(z80))==-1)
  707.     {
  708.         perror(s);
  709.         exit(2);
  710.     }
  711.     if(write(fd,image,z80_size)==-1)
  712.     {
  713.         perror(s);
  714.         exit(2);
  715.     }
  716.     close(fd);
  717. }
  718.  
  719. void jpp_to_vgaspec()
  720. {
  721.     sp=256*jpp.sph+jpp.spl;
  722.     addr=sp-0x4000;
  723.     pc=image[addr]+256*image[addr+1];
  724.     sp=sp+2;
  725.  
  726.     vga.S='S';
  727.     vga.P='P';
  728.     vga.len=0xC000;
  729.     vga.start=0x4000;
  730.     vga.f=jpp.f;
  731.     vga.a=jpp.a;
  732.     vga.b=jpp.b;
  733.     vga.c=jpp.c;
  734.     vga.d=jpp.d;
  735.     vga.e=jpp.e;
  736.     vga.h=jpp.h;
  737.     vga.l=jpp.l;
  738.  
  739.     vga.fax=jpp.fax;
  740.     vga.aax=jpp.aax;
  741.     vga.bax=jpp.bax;
  742.     vga.cax=jpp.cax;
  743.     vga.dax=jpp.dax;
  744.     vga.eax=jpp.eax;
  745.     vga.hax=jpp.hax;
  746.     vga.lax=jpp.lax;
  747.  
  748.     vga.ixh=jpp.ixh;
  749.     vga.ixl=jpp.ixl;
  750.     vga.iyh=jpp.iyh;
  751.     vga.iyl=jpp.iyl;
  752.  
  753.     vga.i=jpp.i;
  754.     vga.r=jpp.r;
  755.  
  756.     vga.im=jpp.im & 0x02; /* 0 for IM1, 2 for IM2 */
  757.  
  758.     /* works? how does it know it was IM1 ? */
  759.     if((jpp.iff2 & 0x04) != 0)
  760.         vga.im=vga.im | 0x01; 
  761.  
  762.     vga.sph=sp/256;
  763.     vga.spl=sp%256;
  764.     
  765.     vga.pch=pc/256;
  766.     vga.pcl=pc%256;
  767.  
  768.     vga.border=jpp.border; 
  769.  
  770.     vga.res2=0;
  771.     vga.res3=0;
  772.     vga.res4=0;
  773.     vga.res5=0;
  774. }
  775.  
  776. void vgaspec_to_jpp()
  777. {
  778.     pc=256*vga.pch+vga.pcl;
  779.         
  780.     jpp.f=vga.f;
  781.     jpp.a=vga.a;
  782.     jpp.b=vga.b;
  783.     jpp.c=vga.c;
  784.     jpp.d=vga.d;
  785.     jpp.e=vga.e;
  786.     jpp.h=vga.h;
  787.     jpp.l=vga.l;
  788.  
  789.     jpp.fax=vga.fax;
  790.     jpp.aax=vga.aax;
  791.     jpp.bax=vga.bax;
  792.     jpp.cax=vga.cax;
  793.     jpp.dax=vga.dax;
  794.     jpp.eax=vga.eax;
  795.     jpp.hax=vga.hax;
  796.     jpp.lax=vga.lax;
  797.  
  798.     jpp.ixh=vga.ixh;
  799.     jpp.ixl=vga.ixl;
  800.     jpp.iyh=vga.iyh;
  801.     jpp.iyl=vga.iyl;
  802.  
  803.     jpp.border=vga.border; 
  804.  
  805.     jpp.i=vga.i;
  806.     jpp.r=vga.r;
  807.  
  808.     /* If register I has changed, chances are good that it runs in
  809.        IM2 mode */
  810.     if(jpp.i==0x3f)
  811.         jpp.im=0x01; 
  812.     else
  813.         jpp.im=0x02; 
  814.         
  815.     if((vga.im & 0x01) == 0)
  816.         jpp.iff2=0x00;
  817.     else
  818.         jpp.iff2=0xff;
  819.  
  820.     sp=256*vga.sph+vga.spl;
  821.     sp=sp-2;
  822.     addr=sp-0x4000;
  823.     image[addr]=vga.pcl;
  824.     image[addr+1]=vga.pch;
  825.         
  826.     jpp.sph=sp/256;
  827.     jpp.spl=sp%256;
  828. }
  829.  
  830. void raw_to_jpp()
  831. {
  832.     pc=0x1bf4; /* entry of "next statement" */
  833.  
  834.     jpp.f=0x99;
  835.     jpp.a=0x5f;
  836.     jpp.b=0x1f;
  837.     jpp.c=0xf0;
  838.     jpp.d=0x5d;
  839.     jpp.e=0x0c;
  840.     jpp.h=0x5d;
  841.     jpp.l=0x0e;
  842.  
  843.     jpp.fax=0x44;
  844.     jpp.aax=0x00;
  845.     jpp.bax=0x18;
  846.     jpp.cax=0x20;
  847.     jpp.dax=0x00;
  848.     jpp.eax=0x07;
  849.     jpp.hax=0x5c;
  850.     jpp.lax=0xf1;
  851.  
  852.     jpp.ixh=0x03;
  853.     jpp.ixl=0xd4;
  854.     jpp.iyh=0x5c;
  855.     jpp.iyl=0x3a;
  856.  
  857.     jpp.i=0x3f;
  858.     jpp.r=0x00;
  859.     jpp.im=0x01;
  860.     jpp.iff2=0xFF;
  861.  
  862.     /* set sp by means of RAMTOP in the image */
  863.     addr=0x5cb2-0x4000;
  864.     sp=256*image[addr+1]+image[addr]-1;
  865.  
  866.     /* Reset ERR NR to no error */
  867.     image[0x5c3a-0x4000]=0xff;
  868.     
  869.     /* Set border by means of BORDCR */
  870.     jpp.border=(image[0x5c48-0x4000] & 0x38)>>3;
  871.     
  872.     /* put return address to MAIN-4 (0x1303) on stack */
  873.     sp=sp-2;
  874.     addr=sp-0x4000;    
  875.     image[addr]=0x03; 
  876.     image[addr+1]=0x13;
  877.     
  878.     sp=sp-2;
  879.     addr=sp-0x4000;
  880.     image[addr]=pc%256;
  881.     image[addr+1]=pc/256;
  882.  
  883.     jpp.sph=sp/256;
  884.     jpp.spl=sp%256;
  885. }
  886.  
  887. void jpp_to_z80()
  888. {
  889.     sp=256*jpp.sph+jpp.spl;
  890.     addr=sp-0x4000;
  891.     pc=image[addr]+256*image[addr+1];
  892.     sp=sp+2;
  893.  
  894.     z80.f=jpp.f;
  895.     z80.a=jpp.a;
  896.     z80.b=jpp.b;
  897.     z80.c=jpp.c;
  898.     z80.d=jpp.d;
  899.     z80.e=jpp.e;
  900.     z80.h=jpp.h;
  901.     z80.l=jpp.l;
  902.  
  903.     z80.fax=jpp.fax;
  904.     z80.aax=jpp.aax;
  905.     z80.bax=jpp.bax;
  906.     z80.cax=jpp.cax;
  907.     z80.dax=jpp.dax;
  908.     z80.eax=jpp.eax;
  909.     z80.hax=jpp.hax;
  910.     z80.lax=jpp.lax;
  911.  
  912.     z80.ixh=jpp.ixh;
  913.     z80.ixl=jpp.ixl;
  914.     z80.iyh=jpp.iyh;
  915.     z80.iyl=jpp.iyl;
  916.  
  917.     z80.i=jpp.i;
  918.     z80.r=jpp.r | 0x080; /* bit 7 is stored somewhere else, always set */
  919.     z80.im=jpp.im & 0x03;
  920.     z80.im=z80.im + 0x60; /* fixed normal video/kempston joystick */
  921.  
  922.     z80.sph=sp/256;
  923.     z80.spl=sp%256;
  924.     
  925.     z80.pch=pc/256;
  926.     z80.pcl=pc%256;
  927.  
  928.     /* all kinds of stuff put in "data" */
  929.     z80.data=(jpp.border & 0x07)*2; 
  930.     if((jpp.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
  931.     z80.data=z80.data | z80_compress();
  932.  
  933.     if((jpp.iff2 & 0x04) != 0)
  934.     {
  935.         z80.iff1=0xff;
  936.         z80.iff2=0xff;
  937.     }
  938.     else
  939.     {
  940.         z80.iff1=0;
  941.         z80.iff2=0;
  942.     }
  943. }
  944.  
  945. void z80_to_jpp()
  946. {
  947.     pc=256*z80.pch+z80.pcl;
  948.         
  949.     jpp.f=z80.f;
  950.     jpp.a=z80.a;
  951.     jpp.b=z80.b;
  952.     jpp.c=z80.c;
  953.     jpp.d=z80.d;
  954.     jpp.e=z80.e;
  955.     jpp.h=z80.h;
  956.     jpp.l=z80.l;
  957.  
  958.     jpp.fax=z80.fax;
  959.     jpp.aax=z80.aax;
  960.     jpp.bax=z80.bax;
  961.     jpp.cax=z80.cax;
  962.     jpp.dax=z80.dax;
  963.     jpp.eax=z80.eax;
  964.     jpp.hax=z80.hax;
  965.     jpp.lax=z80.lax;
  966.  
  967.     jpp.ixh=z80.ixh;
  968.     jpp.ixl=z80.ixl;
  969.     jpp.iyh=z80.iyh;
  970.     jpp.iyl=z80.iyl;
  971.  
  972.     jpp.border=(z80.data/2) & 0x07; 
  973.  
  974.     jpp.i=z80.i;
  975.  
  976.     if(z80.data==0xff) z80.data=0;
  977.  
  978.     if((z80.data & 0x01)==1)
  979.         jpp.r=(z80.r & 0x7f)+0x80;
  980.     else
  981.         jpp.r=z80.r & 0x7f;
  982.  
  983.     jpp.im=z80.im & 0x03;
  984.     
  985.     if(z80.iff2 != 0)
  986.         jpp.iff2=0xff;
  987.     else
  988.         jpp.iff2=0x00;
  989.  
  990.     sp=256*z80.sph+z80.spl;
  991.     sp=sp-2;
  992.     addr=sp-0x4000;
  993.         
  994.     jpp.sph=sp/256;
  995.     jpp.spl=sp%256;
  996.  
  997.     if((z80.data & 0x20)!=0)
  998.         z80_uncompress();
  999.  
  1000.     /* PC can only be stored in the image after decompression!! */
  1001.     image[addr]=z80.pcl;
  1002.     image[addr+1]=z80.pch;
  1003. }
  1004.  
  1005. void z80_uncompress()
  1006. {
  1007.     unsigned char far * uc;
  1008.     unsigned int i,j,k;
  1009.     unsigned char l;
  1010.  
  1011.     uc=farmalloc(IMSIZE+0x0100);
  1012.  
  1013.     if(uc==NULL)
  1014.     {
  1015.         fprintf(stderr,"Not enough memory to uncompress z80 image\n");
  1016.         exit(7);
  1017.     }
  1018.  
  1019.     j=0;
  1020.     i=0;
  1021.     while(i<IMSIZE)
  1022.     {
  1023.         if(image[j]!=0xed)
  1024.             uc[i]=image[j];
  1025.         else if(image[j+1]!=0xed)
  1026.             uc[i]=image[j];
  1027.         else
  1028.         {
  1029.             /* fetch count */
  1030.             k=(int) image[j+2];
  1031.             /* fetch character */
  1032.             l=image[j+3];
  1033.             while(k!=0)
  1034.             {
  1035.                 uc[i]=l;
  1036.                 i++;
  1037.                 k--;
  1038.             }
  1039.             j=j+3;
  1040.             i--;
  1041.         }
  1042.         i++;
  1043.         j++;
  1044.     }
  1045.  
  1046.     if(i!=IMSIZE)
  1047.     {
  1048.         fprintf(stderr,"Z80 image corrupted, can't decompress\n");
  1049.         fprintf(stderr,"i=%u, should be %u\n",i,IMSIZE);
  1050.         exit(6);
  1051.     }
  1052.  
  1053.     /* copy back */
  1054.     j=0;
  1055.     i=0;
  1056.     while(i<IMSIZE)
  1057.         image[j++]=uc[i++];
  1058.  
  1059.     farfree(uc);
  1060. }
  1061.  
  1062. #define NOTCOMPRESSED    0
  1063. #define COMPRESSED    0x20
  1064. #define NO        0
  1065. #define YES        1
  1066.  
  1067. int z80_compress()
  1068. {
  1069.     unsigned char far * comp;
  1070.     unsigned int i,j;
  1071.     unsigned int num;
  1072.     unsigned char c,n;
  1073.     unsigned int ed;
  1074.  
  1075.     z80_size=IMSIZE;
  1076.  
  1077.     comp=farmalloc(IMSIZE+0x0100);
  1078.     if(comp==NULL)
  1079.     {
  1080.         printf("Warning: Not enough memory to compress the image, using uncopressed image\n");
  1081.         return NOTCOMPRESSED;
  1082.     }
  1083.  
  1084.     i=0;
  1085.     j=0;
  1086.     /* ensure 'ed' is not set */
  1087.     ed=NO;
  1088.     while(i<IMSIZE)
  1089.     {
  1090.         c=image[i];
  1091.         i++;
  1092.         if(i<IMSIZE)
  1093.         {
  1094.             n=image[i];
  1095.         }
  1096.         else
  1097.         {
  1098.             /* force 'n' to be unequal to 'c' */
  1099.             n=c;
  1100.             n++;
  1101.         }
  1102.  
  1103.         if(c!=n)
  1104.         {
  1105.             comp[j]=c;
  1106.             j++;
  1107.             if(c==0xed) 
  1108.                 ed=YES;
  1109.             else
  1110.                 ed=NO;
  1111.         }
  1112.         else
  1113.         {
  1114.             if(c==0xed)
  1115.             {
  1116.                 /* two times 0xed - special care */
  1117.                 comp[j]=0xed;
  1118.                 j++;
  1119.                 comp[j]=0xed;
  1120.                 j++;
  1121.                 comp[j]=0x02;
  1122.                 j++;
  1123.                 comp[j]=0xed;
  1124.                 j++;
  1125.                 i++; /* skip second ED */
  1126.  
  1127.                 /* because 0xed is valid compressed we don't
  1128.                    have to watch it! */
  1129.                 ed=NO;
  1130.             }
  1131.             else if(ed==YES)
  1132.             {
  1133.                 /* can't compress now, skip this double pair */
  1134.                 comp[j]=c;
  1135.                 j++;
  1136.                 ed=NO;    /* 'c' can't be 0xed */
  1137.             }
  1138.             else
  1139.             {
  1140.                 num=1;
  1141.                 while(i<IMSIZE)
  1142.                 {
  1143.                     if(c!=image[i])
  1144.                         break;
  1145.                     num++;
  1146.                     i++;
  1147.                     if(num==255)
  1148.                         break;
  1149.                 }
  1150.                 if(num <= 4)
  1151.                 {
  1152.                     /* no use to compress */
  1153.                     while(num!=0)
  1154.                     {
  1155.                         comp[j]=c;
  1156.                         j++;
  1157.                         num--;
  1158.                     }
  1159.                 }
  1160.                 else
  1161.                 {
  1162.                     comp[j]=0xed;
  1163.                     j++;
  1164.                     comp[j]=0xed;
  1165.                     j++;
  1166.                     comp[j]=(unsigned char) num;
  1167.                     j++;
  1168.                     comp[j]=c;
  1169.                     j++;
  1170.                 }
  1171.             }
  1172.         }
  1173.  
  1174.         if(j >= (IMSIZE-4))
  1175.         {
  1176.             /* compressed image bigger or same than original */
  1177.             farfree(comp);
  1178.             return NOTCOMPRESSED;
  1179.         }
  1180.     }
  1181.     /* append "end of compressed area" mark */
  1182.     comp[j]=0;
  1183.     j++;
  1184.     comp[j]=0xed;
  1185.     j++;
  1186.     comp[j]=0xed;
  1187.     j++;
  1188.     comp[j]=0;
  1189.     j++;
  1190.  
  1191.     z80_size = j;
  1192.     
  1193.     /* copy back */
  1194.     i=0;
  1195.     j=0;
  1196.     while(i<IMSIZE)
  1197.         image[i++]=comp[j++];
  1198.     farfree(comp);
  1199.  
  1200.     return COMPRESSED;
  1201. }
  1202.  
  1203. void read_prg(char * s)
  1204. {
  1205.     fd=open(s,O_RDONLY|O_BINARY);
  1206.     if(fd < 0)
  1207.     {
  1208.         perror(s);
  1209.         exit(1);
  1210.     }
  1211.     if(read(fd,&prg,sizeof(prg))==-1)
  1212.     {
  1213.         perror(s);
  1214.         exit(1);
  1215.     }
  1216.     read_image(s);
  1217.     close(fd);
  1218. }
  1219.  
  1220. void write_prg(char * s)
  1221. {
  1222.     unlink(s);
  1223.  
  1224.     fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
  1225.     if(fd<0)
  1226.     {
  1227.         perror(s);
  1228.         exit(2);
  1229.     }
  1230.  
  1231.     if(write(fd,&prg,sizeof(prg))==-1)
  1232.     {
  1233.         perror(s);
  1234.         exit(2);
  1235.     }
  1236.     write_image(s);
  1237.     close(fd);
  1238. }
  1239.  
  1240. void prg_to_jpp()
  1241. {
  1242.     jpp.b=prg.b;
  1243.     jpp.c=prg.c;
  1244.     jpp.d=prg.d;
  1245.     jpp.e=prg.e;
  1246.     jpp.h=prg.h;
  1247.     jpp.l=prg.l;
  1248.     jpp.fax=prg.fax;
  1249.     jpp.aax=prg.aax;
  1250.     jpp.bax=prg.bax;
  1251.     jpp.cax=prg.cax;
  1252.     jpp.dax=prg.dax;
  1253.     jpp.eax=prg.eax;
  1254.     jpp.hax=prg.hax;
  1255.     jpp.lax=prg.lax;
  1256.  
  1257.     jpp.ixh=prg.ixh;
  1258.     jpp.ixl=prg.ixl;
  1259.     jpp.iyh=prg.iyh;
  1260.     jpp.iyl=prg.iyl;
  1261.  
  1262.     /* Set border by means of BORDCR */
  1263.     jpp.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1264.  
  1265.     jpp.i=prg.i;
  1266.  
  1267.     if(prg.i==0x3f)
  1268.         jpp.im=0x01;
  1269.     else
  1270.         jpp.im=0x02;
  1271.  
  1272.     sp=256*prg.sph+prg.spl;
  1273.     sp=sp+4; /* there are two more words on the stack besides PC */
  1274.     addr=sp-0x4000;
  1275.  
  1276.     jpp.r=image[addr-3];
  1277.     /* the af combo is on the stack */
  1278.     jpp.f=image[addr-2];
  1279.     jpp.a=image[addr-1];
  1280.         
  1281.     jpp.sph=sp/256;
  1282.     jpp.spl=sp%256;
  1283.  
  1284.     /* interrupts always on ??? */
  1285.     jpp.iff2=prg.iff2;
  1286. }
  1287.  
  1288. void jpp_to_prg(char * n)
  1289. {
  1290.     int i;
  1291.     unsigned char * p;
  1292.  
  1293.     /* clean header structure first */
  1294.     p=(unsigned char *) &prg;
  1295.     for(i=0; i < 256; i++)
  1296.         p[i]='\0';
  1297.  
  1298.     prg.contains_0x61=0x61; /* size of image in sectors */
  1299.     prg.contains_0x35=0x35; /* don't know yet */
  1300.     prg.contains_0x03=0x03; /* don't know yet */
  1301.  
  1302.     sp=256*jpp.sph+jpp.spl;
  1303.     addr=sp-0x4000;
  1304.  
  1305.     /* these are on the stack */
  1306.     image[addr-1]=jpp.a;
  1307.     image[addr-2]=jpp.f;
  1308.     image[addr-3]=jpp.r;
  1309.     image[addr-4]=jpp.iff2;
  1310.  
  1311.     sp=sp-4;
  1312.  
  1313.     prg.name[0]='\0';
  1314.     strncpy(prg.name,n,10);
  1315.     prg.name[10]='\0';
  1316.  
  1317.     prg.b=jpp.b;
  1318.     prg.c=jpp.c;
  1319.     prg.d=jpp.d;
  1320.     prg.e=jpp.e;
  1321.     prg.h=jpp.h;
  1322.     prg.l=jpp.l;
  1323.  
  1324.     prg.fax=jpp.fax;
  1325.     prg.aax=jpp.aax;
  1326.     prg.bax=jpp.bax;
  1327.     prg.cax=jpp.cax;
  1328.     prg.dax=jpp.dax;
  1329.     prg.eax=jpp.eax;
  1330.     prg.hax=jpp.hax;
  1331.     prg.lax=jpp.lax;
  1332.  
  1333.     prg.ixh=jpp.ixh;
  1334.     prg.ixl=jpp.ixl;
  1335.     prg.iyh=jpp.iyh;
  1336.     prg.iyl=jpp.iyl;
  1337.  
  1338.     prg.i=jpp.i;
  1339.     prg.iff2=jpp.iff2;
  1340.  
  1341.     prg.sph=sp/256;
  1342.     prg.spl=sp%256;
  1343.     
  1344.     /* prg.border=jpp.border; */
  1345. }
  1346.