home *** CD-ROM | disk | FTP | other *** search
/ ARM Club 1 / ARM_CLUB_CD.iso / contents / apps / emulate / progs / spconv / !Spconv_UnixSource_c_spconv < prev    next >
Encoding:
Text File  |  1994-06-27  |  38.1 KB  |  1,849 lines

  1. /*
  2.  * SPCONV -    ZX-Spectrum 48K snapshot converter
  3.  *
  4.  *        Public Domain software
  5.  *
  6.  * Author: Henk de Groot
  7.  */
  8.  
  9. #if defined(__STDC__) || defined(__TURBOC__)
  10. #include <stdlib.h>
  11. #else
  12. #include <sys/types.h>
  13. #endif
  14.  
  15. #ifdef __TURBOC__
  16. #include <io.h>
  17. #else
  18. #include <unistd.h>
  19. #endif
  20.  
  21. #include <stdio.h>
  22. #include <fcntl.h>
  23. #include <sys/stat.h>
  24. #include <string.h>
  25. #include <ctype.h>
  26. /* #ifdef __TURBOC__
  27. #include <alloc.h>
  28. #else
  29. #include <malloc.h>
  30. #endif    */
  31.  
  32. #ifndef O_BINARY
  33. #define O_BINARY 0
  34. #endif
  35.  
  36. #include "spconv.h"
  37.  
  38. struct sna_s sna;
  39. struct vga_s vga;
  40. struct z80_s z80;
  41. struct prg_s prg;
  42. struct ach_s ach;
  43. struct kgb_s kgb;
  44.  
  45. /* extra space just in case the Z80 decompress fails due to a corrupt image */
  46. unsigned char image[IMSIZE+0x100]; 
  47. unsigned int z80_size;
  48.  
  49. int    intype;
  50. int    outtype;
  51.  
  52. /* Path names are limited to 80 characters under MSDOS so this sould be */
  53. /* enough... If you are using UNIX than you may have to make this array */
  54. /* larger.                                                              */
  55. char    my_directory[120];
  56.  
  57. int main(int argc,char *argv[])
  58. {
  59.     char        *p;
  60.     struct stat    status;
  61.     const char *    fromstring;
  62.     const char *    tostring;
  63.     char *        outfile;
  64.     long        file_size;
  65.  
  66. #ifdef __TURBOC__
  67.     /* for Trubo-C: open all files in binary mode */
  68.     extern int _fmode;
  69.     _fmode = O_BINARY;
  70. #endif
  71.  
  72.     if(argc != 3)
  73.         USAG_usage();
  74.  
  75.     if((strchr(argv[1],'*')!=NULL) || (strrchr(argv[1],'?')!=NULL) ||
  76.        (strchr(argv[2],'*')!=NULL) || (strrchr(argv[2],'?')!=NULL))    {
  77.         fprintf(stderr,"This program can't handle wildcards, sorry!\n");
  78.         return EXIT_USAGE;
  79.     }
  80.  
  81.     /*
  82.      * Find the directory path where this program is started from.
  83.      * This will be needed for finding the spectrum-rom. Some formats
  84.      * need the spectrum-rom for proper conversion.
  85.      */
  86.     strcpy(my_directory,argv[0]);
  87.     if(strrchr(my_directory,'\\')!=NULL) {
  88.         *strrchr(my_directory,'\\')='\0';
  89.     }
  90.     else if(strrchr(my_directory,'/')!=NULL) {
  91.         *strrchr(my_directory,'/')='\0';
  92.     }
  93.     else if(strrchr(my_directory,':')!=NULL) {
  94.         *strrchr(my_directory,':')='\0';
  95.     } else {
  96.         my_directory[0]='\\';
  97.         my_directory[1]='\0';
  98.     }
  99.  
  100.     /*
  101.      * Check if the input file exists and fetch the file lenght of
  102.      * the file in the mean time. Two for the prise of one...
  103.      */
  104.     if(stat(argv[1],&status)<0) {
  105.         perror(argv[1]);
  106.         return EXIT_FILE_ERROR;
  107.     }
  108.     file_size = status.st_size;
  109.  
  110.     /* 
  111.      * recognize input type on filename:
  112.      *
  113.      *    .SNA    ->    SNA file (used in JPP)
  114.      *    .SP    ->    SP file (was VGASPEC)
  115.      *    .Z80    ->    Z80 file
  116.      *    .PRG    ->    PRG file
  117.      *    .ACH    ->    ACH file (from archimedes emulator)
  118.      *    .ZX    ->    KGB file (from KGB emulator)
  119.      *    other    ->    if exact 48+header -> raw file
  120.      *    otherwise     unknown
  121.      */
  122.  
  123.     fromstring = DTYP_determine_type(argv[1],&intype);
  124.  
  125.     if (intype == UNKNOWN) {
  126.         if (file_size == (hdr_size+IMSIZE)) {
  127.             fromstring="RAW";
  128.             intype=RAW;
  129.         } else {
  130.             fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH or\n");
  131.             fprintf(stderr,".ZX file, or a Raw file\n");
  132.             return EXIT_FILE_ERROR;
  133.         }
  134.     }
  135.  
  136.     /* 
  137.      * recognize output type on filename:
  138.      *
  139.      *    .SNA    ->    SNA file
  140.      *    .SP    ->    SP file (was VGASPEC)
  141.      *    .Z80    ->    Z80 file
  142.      *    .PRG    ->    PRG file
  143.      *    .ACH    ->    ACH file (from archimedes emulator)
  144.      *    .ZX    ->    KGB file (from KGB emulator)
  145.      *    otherwise     unknown
  146.      */
  147.  
  148.     tostring = DTYP_determine_type(argv[2],&outtype);
  149.  
  150.     if(outtype==UNKNOWN) {
  151.         fprintf(stderr,"Unknown output file format. Must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file\n");
  152.         return EXIT_FILE_ERROR;
  153.     }
  154.  
  155.     /* 
  156.      * if argv[2] only contains the suffix then use the prefix of
  157.      * argv[1];
  158.      */
  159.     if(argv[2][0]=='.') {
  160.         outfile=malloc(strlen(argv[1])+strlen(argv[2])+1);
  161.         strcpy(outfile,argv[1]); /* copy prefix    */
  162.  
  163.         p=strrchr(outfile,'.');
  164.         if(p!=NULL) *p='\0'; /* put end of string at position of '.' */
  165.  
  166.         strcat(outfile,argv[2]); /* append suffix  */
  167.     } else {
  168.         outfile=malloc(strlen(argv[2])+1);
  169.  
  170.         strcpy(outfile,argv[2]);
  171.     }
  172.  
  173.     /*
  174.      * Special converion between versions of the same type
  175.      */
  176.     if(intype == outtype)
  177.         return DIRC_direct_convert(intype, argv[1], outfile);
  178.  
  179.     /*
  180.      * General conversion from one type to another
  181.      */
  182.  
  183.     printf("Converting %s from %s to %s\n",argv[1],fromstring,tostring);
  184.  
  185.     /*
  186.      * convert input_file to SNA
  187.      */
  188.  
  189.     switch(intype) {
  190.     case SNA:    if (file_size == (sna_size+IMSIZE)) {
  191.                 RSNA_read_sna(argv[1]);
  192.             }
  193.             break;
  194.     case SP:    if ((file_size == (vga_size+IMSIZE))) {
  195.                 RVGA_read_vgaspec(argv[1]);
  196.                 VGSN_vgaspec_to_sna();
  197.             } else if ((file_size == (vga_size+IMSIZE-6))) {
  198.                 ROVG_read_old_vgaspec(argv[1]);
  199.                 VGSN_vgaspec_to_sna();
  200.             }
  201.             break;
  202.     case RAW:    RRAW_read_raw(argv[1]);
  203.             RASN_raw_to_sna();
  204.             break;
  205.     case Z80:    RZ80_read_z80(argv[1]);
  206.             Z8SN_z80_to_sna();
  207.             break;
  208.     case PRG:    if(file_size != (prg_size+IMSIZE)) {
  209.                 printf("Warning: the image part of %s is not exactly 48k!\n",argv[1]);
  210.                 printf("         Converting anyway, the converted file may not work\n");
  211.             }
  212.             RPRG_read_prg(argv[1]);
  213.             PRSN_prg_to_sna();
  214.             break;
  215.     case ACH:    if(file_size == (ach_size+16384L+IMSIZE)) {
  216.                 RACH_read_ach(argv[1]);
  217.                 ACSN_ach_to_sna();
  218.             }
  219.             break;
  220.     case KGB:    if(file_size == (132L+IMSIZE+kgb_size)) {
  221.                 RKGB_read_kgb(argv[1]);
  222.                 KGSN_kgb_to_sna();
  223.             }
  224.             break;
  225.     default:    printf("Unrecognized input file type, can't convert\n");
  226.             return EXIT_FILE_ERROR;
  227.     }
  228.  
  229.     /*
  230.      * convert internal SNA format to output file
  231.      */
  232.  
  233.     switch(outtype) {
  234.     case SNA:    WSNA_write_sna(outfile);
  235.             break;
  236.     case SP:    SNVG_sna_to_vgaspec();
  237.             WVGA_write_vgaspec(outfile);
  238.             break;
  239.     case Z80:    SNZ8_sna_to_z80();
  240.             WZ80_write_z80(outfile);
  241.             break;
  242.     case PRG:    SNPR_sna_to_prg(outfile);
  243.             WPRG_write_prg(outfile);
  244.             break;
  245.     case ACH:    SNAC_sna_to_ach();
  246.             WACH_write_ach(outfile);
  247.             break;
  248.     case KGB:    SNKG_sna_to_kgb();
  249.             WKGB_write_kgb(outfile);
  250.             break;
  251.     default:    printf("Unrecognized output file type, can't convert\n");
  252.             return EXIT_FILE_ERROR;
  253.     }
  254.  
  255.     /*
  256.      * That's it, simple isn't it?
  257.      */
  258.     return EXIT_OK;
  259. }
  260.  
  261. /* SPECIAL FUNCTIONS */
  262.  
  263. /* Determine file type and return both type and type-name */
  264.  
  265. const char * DTYP_determine_type(char * filename, int * type)
  266. {
  267.     const char *p;
  268.     char ext[5];
  269.     int  i;
  270.  
  271.     /*
  272.      * recognize type on filename:
  273.      *
  274.      *    .SNA    ->    SNA file
  275.      *    .SP    ->    SP file (was VGASPEC)
  276.      *    .Z80    ->    Z80 file
  277.      *    .PRG    ->    PRG file
  278.      *    .ACH    ->    ACH file (from archimedes emulator)
  279.      *    .ZX    ->    KGB file (from KGB emulator)
  280.      *    otherwise     unknown
  281.      */
  282.  
  283.     *type=UNKNOWN;    /* default if all ifs below fail */
  284.  
  285.     p=strrchr(filename,'.');
  286.     if(p==NULL) p=filename; /* not found, set at begin of string */
  287.  
  288.     /* Take extension and convert to uppercase */
  289.     for(i = 0; i < 4; i++) {
  290.         if(*p != '\0') {
  291.             ext[i] = toupper(*p);
  292.             p++;
  293.         } else {
  294.             ext[i] = '\0';
  295.         }
  296.     }
  297.     ext[4] = '\0'; /* termination at least on the fifth char */
  298.  
  299.     if(strcmp(ext,".SNA")==0) {
  300.         *type=SNA;
  301.         return ".SNA";
  302.     }
  303.     if(strcmp(ext,".Z80")==0) {
  304.         *type=Z80;
  305.         return ".Z80";
  306.     }
  307.     if(strcmp(ext,".SP")==0) {
  308.         *type=SP;
  309.         return ".SP";
  310.     }
  311.     if(strcmp(ext,".PRG")==0) {
  312.         *type=PRG;
  313.         return ".PRG";
  314.     }
  315.     if(strcmp(ext,".ACH")==0) {
  316.         *type=ACH;
  317.         return ".ACH";
  318.     }
  319.     if(strcmp(ext,".ZX")==0) {
  320.         *type=KGB;
  321.         return ".ZX";
  322.     }
  323.  
  324.     /* unknown type, return question-mark */
  325.     return "?";
  326. }
  327.  
  328. /* Special converion between versions of the same type */
  329.  
  330. int DIRC_direct_convert(int type, char * infile, char * outfile)
  331. {
  332.     struct stat status;
  333.     long        file_size;
  334.  
  335.     /*
  336.      * Special conversion between versions of the same type.
  337.      * These conversion don't use the intermediate 'sna' format
  338.      * to preserve as much information as possible.
  339.      *
  340.      * This currently only applies to .SP and the .Z80 formats.
  341.      *
  342.      * The .SP formats will convert from the New to the Old format or
  343.      * from the Old to the New format, controled by the current format
  344.      * of the input.
  345.      *
  346.      * The .Z80 formats will convert to the version 1.45 .Z80 format
  347.      * since version 1.45 .Z80 files can be read by both old and new
  348.      * Z80-emulators.
  349.      */
  350.  
  351.     /* check if it is for the SP format */
  352.     if(type == SP) {
  353.         if(stat(infile,&status)<0) {
  354.             perror(infile);
  355.             return EXIT_FILE_ERROR;
  356.         }
  357.         file_size = status.st_size;
  358.  
  359.         if((file_size == (vga_size+IMSIZE))) {
  360.             printf("Converting %s from new .SP format to old .SP format.\n",infile);
  361.             RVGA_read_vgaspec(infile);
  362.  
  363.             WOVG_write_old_vgaspec(outfile);
  364.             return EXIT_OK;
  365.         }
  366.  
  367.         if((file_size == (vga_size+IMSIZE-6))) {
  368.             RVGH_read_vgaspec_header(infile);
  369.  
  370.             if((vga.S=='S')&&(vga.P=='P')) {
  371. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  372. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  373. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  374. fprintf(stderr,"contain images of 48Kb length.\n");
  375.                 return EXIT_FILE_ERROR;
  376.             }
  377.  
  378.             printf("Converting %s from old .SP format to new .SP format.\n",infile);
  379.             ROVG_read_old_vgaspec(infile);
  380.  
  381.             /* These values are fixed for a full 48K .SP file */
  382.             vga.S='S';
  383.             vga.P='P';
  384.             vga.len_l=0x00;
  385.             vga.len_h=0xC0;
  386.             vga.start_l=0x00;
  387.             vga.start_h=0x40;
  388.  
  389.             WVGA_write_vgaspec(outfile);
  390.  
  391.             return EXIT_OK;
  392.         } else {
  393.             RVGH_read_vgaspec_header(infile);
  394.             if((vga.S=='S')&&(vga.P=='P')) {
  395. fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
  396. fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
  397. fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
  398. fprintf(stderr,"contain images of 48Kb length.\n");
  399.             } else {
  400. fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or RAW file\n");
  401.             }
  402.             return EXIT_FILE_ERROR;
  403.         }
  404.     }
  405.  
  406.     if(type == Z80)
  407.     {
  408.         printf("Converting %s from .Z80 to .Z80 (output in version 1.45 format)\n",infile);
  409.         RZ80_read_z80(infile);
  410.  
  411.         WZ80_write_z80(outfile);
  412.         return EXIT_OK;
  413.     }
  414.  
  415.     /* If we get here than we had no special handling for this type */
  416.     /* return an error in that case...                              */
  417.     fprintf(stderr,"Input and output file format are the same. ");
  418.     fprintf(stderr,"What you try to do\n");
  419.     fprintf(stderr,"is handled much better by the MSDOS \"COPY\" ");
  420.     fprintf(stderr,"command!\n");
  421.  
  422.     return EXIT_USAGE;
  423. }
  424.  
  425. /* ERROR HANDLING FUNCTIONS */
  426.  
  427. /* Print Usage and exit */
  428. void USAG_usage()
  429. {
  430.     fprintf(stderr,"SPCONV version 1.07 - %s\n\n",__DATE__);
  431.     fprintf(stderr,"Usage: spconv <source> <target>\n\n");
  432.     fprintf(stderr,"Source must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or RAW file.\n");
  433.     fprintf(stderr,"Target must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file.\n\n");
  434.     fprintf(stderr,"If the second parameter contains only a suffix, the prefix\n");
  435.     fprintf(stderr,"of the input file will be used (i.e. 'spconv file.sna .z80')\n\n");
  436.     fprintf(stderr,"Output .SP files are in the new format, .Z80 files are compressed\n");
  437.     fprintf(stderr,"in the version 1.45 .Z80 format\n\n");
  438.     fprintf(stderr,"If <source> and <target> are .SP files, convertion from old\n");
  439.     fprintf(stderr,"to new format or from new to old format will be performed.\n");
  440.     fprintf(stderr,"If <source> and <target> are .Z80 files, convertion to\n");
  441.     fprintf(stderr,"the version 1.45 format will be performed.\n");
  442.     fprintf(stderr,"If <source> and <target> are of the same type an error message\n");
  443.     fprintf(stderr,"will be generated (unless they are both .SP or .Z80 files)\n");
  444.     fprintf(stderr,"\n\nPublic Domain, H. de Groot 1994\n\n");
  445.  
  446.     exit(EXIT_USAGE);
  447. }
  448.  
  449. void RERR_read_error(char * s, FILE * fd)
  450. {
  451.     perror(s);
  452.     if(fd != NULL) fclose(fd);
  453.     exit(EXIT_READ_ERROR);
  454. }
  455.  
  456. void WERR_write_error(char * s, FILE * fd)
  457. {
  458.     perror(s);
  459.     if(fd != NULL) fclose(fd);
  460.     exit(EXIT_WRITE_ERROR);
  461. }
  462.  
  463. /* I/O FUNCTIONS */
  464.  
  465. /* GENERIC I/O - READ/WRITE SNAPSHOT */
  466.  
  467. void RGEN_read_generic(char * s, void * header, size_t h_size)
  468. {
  469.     FILE * fd;
  470.  
  471.     fd=fopen(s,"r");
  472.     if(fd == NULL)
  473.         RERR_read_error(s, fd);
  474.  
  475.     if(fread(header, h_size, 1, fd)!=1)
  476.         RERR_read_error(s, fd);
  477.  
  478.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  479.         RERR_read_error(s, fd);
  480.  
  481.     fclose(fd);
  482. }
  483.  
  484. void WGEN_write_generic(char * s, void * header, size_t h_size)
  485. {
  486.     FILE * fd;
  487.  
  488.     unlink(s);
  489.  
  490.     fd=fopen(s,"w");
  491.     if(fd == NULL)
  492.         WERR_write_error(s, fd);
  493.  
  494.     if(fwrite(header, h_size, 1, fd)!=1)
  495.         WERR_write_error(s, fd);
  496.  
  497.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  498.         WERR_write_error(s, fd);
  499.  
  500.     fclose(fd);
  501. }
  502.  
  503. /* SPECIFIC I/O - READ/WRITE .SNA IMAGE */
  504.  
  505. void RSNA_read_sna(char * s)
  506. {
  507.     RGEN_read_generic(s, (void *) &sna, sna_size);
  508. }
  509.  
  510. void WSNA_write_sna(char * s)
  511. {
  512.     WGEN_write_generic(s, (void *) &sna, sna_size);
  513. }
  514.  
  515. /* SPECIFIC I/O - READ NEW .SP HEADER */
  516.  
  517. void RVGH_read_vgaspec_header(char * s)
  518. {
  519.     FILE * fd;
  520.  
  521.     fd=fopen(s,"r");
  522.     if(fd == NULL)
  523.         RERR_read_error(s, fd);
  524.  
  525.     if(fread(&vga,vga_size,1,fd)!=1)
  526.         RERR_read_error(s, fd);
  527.  
  528.     fclose(fd);
  529. }
  530.  
  531. /* SPECIFIC I/O - READ/WRITE NEW .SP IMAGE */
  532.  
  533. void RVGA_read_vgaspec(char * s)
  534. {
  535.     RGEN_read_generic(s, (void *) &vga, vga_size);
  536. }
  537.  
  538. void WVGA_write_vgaspec(char * s)
  539. {
  540.     WGEN_write_generic(s, (void *) &vga, vga_size);
  541. }
  542.  
  543. /* SPECIFIC I/O - READ/WRITE OLD .SP IMAGE */
  544.  
  545. void ROVG_read_old_vgaspec(char * s)
  546. {
  547.     RGEN_read_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
  548. }
  549.  
  550. void WOVG_write_old_vgaspec(char * s)
  551. {
  552.     WGEN_write_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
  553. }
  554.  
  555. /* SPECIFIC I/O - READ RAW IMAGE */
  556.  
  557. void RRAW_read_raw(char * s)
  558. {
  559.     int i;
  560.     FILE * fd;
  561.  
  562.     fd=fopen(s,"r");
  563.     if(fd == NULL)
  564.         RERR_read_error(s, fd);
  565.  
  566.     if(fread(&h, hdr_size, 1, fd)!=1)
  567.         RERR_read_error(s, fd);
  568.  
  569.     /* check if the image was saved the correct way */
  570.     for(i=0;i<9;i++) {
  571.         if(h.in[i]!=expect[i]) {
  572.             fprintf(stderr,"Header of spectum image not ok, ");
  573.             fprintf(stderr,"Spectrum image should be saved with:\n");
  574.             fprintf(stderr,"SAVE *\"b\"CODE 16384,49152");
  575.             fclose(fd);
  576.             exit(EXIT_FILE_ERROR);
  577.         }
  578.     }
  579.  
  580.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  581.         RERR_read_error(s, fd);
  582.  
  583.     fclose(fd);
  584. }
  585.  
  586. /* SPECIFIC I/O - READ/WRITE .Z80 IMAGE */
  587.  
  588. void RZ80_read_z80(char * s)
  589. {
  590.     FILE * fd;
  591.  
  592.     fd=fopen(s,"r");
  593.     if(fd == NULL)
  594.         RERR_read_error(s, fd);
  595.  
  596.     /* read old header part */
  597.     if(fread(&z80,z80_145_size,1,fd)!=1)
  598.         RERR_read_error(s, fd);
  599.  
  600.     /* check for 2.01 format */
  601.     if((z80.pch == (unsigned char) 0) &&
  602.        (z80.pcl == (unsigned char) 0)) {
  603.  
  604.         /* 2.01 or better format, check if we can use this */
  605.         unsigned char *p;
  606.         p = (unsigned char *) &z80;
  607.  
  608.         /* read an aditional 2 bytes */
  609.         if(fread(&p[z80_145_size],2,1,fd)!=1)
  610.             RERR_read_error(s, fd);
  611.  
  612.         if((p[z80_145_size] != (unsigned char) 23) &&
  613.            (p[z80_145_size+1] != (unsigned char) 0)) {
  614.             fprintf(stderr,"%s seems to be a new type Z80 file!\n",s);
  615.             fprintf(stderr,"This program can only read files up to version 2.01 format\n");
  616.             fclose(fd);
  617.             exit(EXIT_FILE_ERROR);
  618.         }
  619.  
  620.         /* we passed this test, read the 23 byte long extra header */
  621.         if(fread(&p[z80_145_size+2],23,1,fd)!=1)
  622.             RERR_read_error(s, fd);
  623.  
  624.         /* we got a complete header now. */
  625.         /* check the type of the file... */
  626.         if((unsigned int) z80.hardware >= 3) {
  627.             fprintf(stderr,"%s is not a 48K Spectrum Z80 file, can't convert!\n",s);
  628.             fclose(fd);
  629.             exit(EXIT_FILE_ERROR);
  630.         }
  631.         /* check if the interface-1 rom was paged in */
  632.         if(z80.if1_paged != (unsigned char) 0) {
  633.             fprintf(stderr,"%s has interface-1 rom paged in, can't convert!\n",s);
  634.             fclose(fd);
  635.             exit(EXIT_FILE_ERROR);
  636.         }
  637.         /* all fine up till now, put PC back to the old place and reset the */
  638.         /* compressed memory bit, the z80_read_page function decompresses.  */
  639.         z80.pch = z80.n_pch;
  640.         z80.pcl = z80.n_pcl;
  641.         z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  642.  
  643.         while(RDPG_z80_read_page(s, fd)!=0);
  644.     } else {
  645.         /* The file is in version 1.45 format.             */
  646.         /* Read and decompress if the image is compressed, */
  647.         /* just read if it is not compressed at all...     */
  648.  
  649.         if((z80.data & 0x20)!=0) {
  650.             Z80D_z80_decompress(fd,0,(unsigned int) IMSIZE);
  651.             z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  652.         } else {
  653.             if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  654.                 RERR_read_error(s, fd);
  655.         }
  656.     }
  657.     fclose(fd);
  658. }
  659.  
  660. void WZ80_write_z80(char * s)
  661. {
  662.     FILE * fd;
  663.  
  664.     /* Try to compress the data */
  665.     z80.data=z80.data | Z80C_z80_compress();
  666.  
  667.     unlink(s);
  668.  
  669.     fd=fopen(s,"w");
  670.     if(fd == NULL)
  671.         WERR_write_error(s, fd);
  672.  
  673.     if(fwrite(&z80, z80_145_size, 1, fd)!=1)
  674.         WERR_write_error(s, fd);
  675.  
  676.     if(fwrite(image, (size_t) z80_size, 1, fd)!=1)
  677.         WERR_write_error(s, fd);
  678.  
  679.     fclose(fd);
  680. }
  681.  
  682. /* SPECIFIC I/O - READ/WRITE .PRG IMAGE */
  683.  
  684. void RPRG_read_prg(char * s)
  685. {
  686.     RGEN_read_generic(s, (void *) &prg, prg_size);
  687. }
  688.  
  689. void WPRG_write_prg(char * s)
  690. {
  691.     WGEN_write_generic(s, (void *) &prg, prg_size);
  692. }
  693.  
  694. /* SPECIFIC I/O - READ/WRITE .ACH IMAGE */
  695.  
  696. void RACH_read_ach(char * s)
  697. {
  698.     FILE * fd;
  699.  
  700.     fd=fopen(s,"r");
  701.     if(fd == NULL)
  702.         RERR_read_error(s, fd);
  703.  
  704.     if(fread(&ach,ach_size,1,fd)!=1)
  705.         RERR_read_error(s, fd);
  706.  
  707.     /* fseek over the 16K ram area */
  708.     if(fseek(fd,16384L,SEEK_CUR)!=0)
  709.         RERR_read_error(s, fd);
  710.  
  711.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  712.         RERR_read_error(s, fd);
  713.  
  714.     fclose(fd);
  715. }
  716.  
  717. void WACH_write_ach(char * s)
  718. {
  719.     char buffer[1024];
  720.     char *p;
  721.     int  i;
  722.     struct stat status;
  723.     const char * rom;
  724.     FILE * fd;
  725.     long file_size;
  726.  
  727.     /* clean buffer first */
  728.     p=(char *) buffer;
  729.     for(i=0; i < 1024; i++) p[i]='\0';
  730.  
  731.     unlink(s);
  732.  
  733.     fd=fopen(s,"w");
  734.     if(fd == NULL)
  735.         WERR_write_error(s, fd);
  736.  
  737.     if(fwrite(&ach,ach_size,1,fd)!=1)
  738.         WERR_write_error(s, fd);
  739.  
  740.     strcat(my_directory,"\\spectrum.rom");
  741.  
  742.     rom=NULL;
  743.  
  744.     if(stat("spectrum.rom",&status)>=0) {
  745.         rom="spectrum.rom";
  746.     }
  747.     else if (stat(my_directory,&status)>=0)    {
  748.         rom=(const char *) my_directory;
  749.     }
  750.     file_size = status.st_size;
  751.  
  752.     if(rom==NULL) {
  753.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
  754.         printf("         format could not be located, Converting anyway. The ROM space\n");
  755.         printf("         will be filled with 0 bytes, the converted file may not work\n");
  756.  
  757.         /* write the 16K ram area as zero's */
  758.         for(i=0; i < 16; i++) {
  759.             if(fwrite(buffer,1024,1,fd)!=1)
  760.                 WERR_write_error(s, fd);
  761.         }
  762.     } else {
  763.         if (file_size != 16384) {
  764.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
  765.         printf("         format has a wrong size (not 16K). Converting anyway. The ROM space\n");
  766.         printf("         will be filled with 0 bytes, the converted file may not work\n");
  767.  
  768.             /* copy the 16K ROM area */
  769.             for(i=0; i < 16; i++) {
  770.                 if(fwrite(buffer,1024,1,fd)!=1)
  771.                     WERR_write_error(s, fd);
  772.             }
  773.         } else {
  774.             FILE * fd_specrom;
  775.  
  776.             printf("Using Spectrum ROM: %s\n",rom);
  777.  
  778.             fd_specrom=fopen(rom,"r");
  779.             if(fd_specrom==NULL) {
  780.                 perror(rom);
  781.                 fclose(fd);
  782.                 exit(EXIT_WRITE_ERROR);
  783.             }
  784.  
  785.             for(i=0; i < 16; i++) {
  786.                 if(fread(buffer,1024,1,fd_specrom)!=1) {
  787.                     perror(rom);
  788.                     fclose(fd_specrom);
  789.                     fclose(fd);
  790.                     exit(EXIT_WRITE_ERROR);
  791.                 }
  792.                 if(fwrite(buffer,1024,1,fd)!=1) {
  793.                     perror(s);
  794.                     fclose(fd_specrom);
  795.                     fclose(fd);
  796.                     exit(EXIT_WRITE_ERROR);
  797.                 }
  798.             }
  799.             fclose(fd_specrom);
  800.         }
  801.     }
  802.  
  803.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  804.         WERR_write_error(s, fd);
  805.  
  806.     fclose(fd);
  807. }
  808.  
  809. /* SPECIFIC I/O - READ/WRITE .ZX IMAGE */
  810.  
  811. void RKGB_read_kgb(char * s)
  812. {
  813.     FILE * fd;
  814.  
  815.     fd=fopen(s,"r");
  816.     if(fd == NULL)
  817.         RERR_read_error(s, fd);
  818.  
  819.     /* fseek over the first 132 bytes */
  820.     if(fseek(fd,132L,SEEK_CUR)!=0)
  821.         RERR_read_error(s, fd);
  822.  
  823.     if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
  824.         RERR_read_error(s, fd);
  825.  
  826.     if(fread(&kgb,kgb_size,1,fd)!=1)
  827.         RERR_read_error(s,fd);
  828.  
  829.     fclose(fd);
  830. }
  831.  
  832. void WKGB_write_kgb(char * s)
  833. {
  834.     char buffer[132];
  835.     char *p;
  836.     int  i;
  837.     struct stat status;
  838.     const char * rom;
  839.     FILE * fd;
  840.     long file_size;
  841.  
  842.     /* clean buffer first */
  843.     p=(char *) buffer;
  844.     for(i=0; i < 132; i++) p[i]='\0';
  845.  
  846.     unlink(s);
  847.  
  848.     fd=fopen(s,"w");
  849.     if(fd == NULL)
  850.         WERR_write_error(s, fd);
  851.  
  852.     strcat(my_directory,"\\spectrum.rom");
  853.  
  854.     rom=NULL;
  855.  
  856.     if(stat("spectrum.rom",&status)>=0) {
  857.         rom="spectrum.rom";
  858.     }
  859.     else if (stat(my_directory,&status)>=0) {
  860.         rom=(const char *) my_directory;
  861.     }
  862.     file_size = status.st_size;
  863.  
  864.     if(rom==NULL) {
  865.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
  866.         printf("         format could not be located, Converting anyway. The 132 bytes needed\n");
  867.         printf("         from the ROM will be filled with 0 bytes, the converted file may not\n");
  868.         printf("         work\n");
  869.  
  870.         /* write the 132 byte area as zero's */
  871.         if(fwrite(buffer,132,1,fd)!=1)
  872.             WERR_write_error(s, fd);
  873.     } else {
  874.         if (file_size != 16384) {
  875.         printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
  876.         printf("         format has a wrong size (not 16K). Converting anyway. The 132 bytes\n");
  877.         printf("         needed from the ROM will be filled with 0 bytes, the converted file\n");
  878.         printf("         may not work\n");
  879.  
  880.             /* write the 132 byte area as zero's */
  881.             if(fwrite(buffer,132,1,fd)!=1)
  882.                 WERR_write_error(s, fd);
  883.         } else {
  884.             FILE * fd_specrom;
  885.  
  886.             printf("Using Spectrum ROM: %s\n",rom);
  887.  
  888.             fd_specrom=fopen(rom,"r");
  889.  
  890.             if(fd_specrom == NULL) {
  891.                 perror(rom);
  892.                 fclose(fd);
  893.                 exit(EXIT_WRITE_ERROR);
  894.             }
  895.  
  896.             /* fseek over the first 16384-132 bytes */
  897.             if(fseek(fd_specrom,16252L,SEEK_CUR)!=0) {
  898.                 perror(rom);
  899.                 fclose(fd_specrom);
  900.                 fclose(fd);
  901.                 exit(EXIT_WRITE_ERROR);
  902.             }
  903.             if(fread(buffer,132,1,fd_specrom)!=1) {
  904.                 perror(rom);
  905.                 fclose(fd_specrom);
  906.                 fclose(fd);
  907.                 exit(EXIT_WRITE_ERROR);
  908.             }
  909.             if(fwrite(buffer,132,1,fd)!=1) {
  910.                 perror(s);
  911.                 fclose(fd_specrom);
  912.                 fclose(fd);
  913.                 exit(EXIT_WRITE_ERROR);
  914.             }
  915.             fclose(fd_specrom);
  916.         }
  917.     }
  918.  
  919.     if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
  920.         WERR_write_error(s, fd);
  921.  
  922.     if(fwrite(&kgb,kgb_size,1,fd)!=1)
  923.         WERR_write_error(s, fd);
  924.  
  925.     fclose(fd);
  926. }
  927.  
  928. /* CONVERSION FUNCTIONS - TO .SNA FORMAT */
  929.  
  930. void VGSN_vgaspec_to_sna()
  931. {
  932.     unsigned int addr;
  933.     unsigned int sp;
  934.  
  935.     sna.f=vga.f;
  936.     sna.a=vga.a;
  937.     sna.b=vga.b;
  938.     sna.c=vga.c;
  939.     sna.d=vga.d;
  940.     sna.e=vga.e;
  941.     sna.h=vga.h;
  942.     sna.l=vga.l;
  943.  
  944.     sna.fax=vga.fax;
  945.     sna.aax=vga.aax;
  946.     sna.bax=vga.bax;
  947.     sna.cax=vga.cax;
  948.     sna.dax=vga.dax;
  949.     sna.eax=vga.eax;
  950.     sna.hax=vga.hax;
  951.     sna.lax=vga.lax;
  952.  
  953.     sna.ixh=vga.ixh;
  954.     sna.ixl=vga.ixl;
  955.     sna.iyh=vga.iyh;
  956.     sna.iyl=vga.iyl;
  957.  
  958.     sna.border=vga.border; 
  959.  
  960.     sna.i=vga.i;
  961.     sna.r=vga.r;
  962.  
  963.     /* If register I has changed, chances are good that it runs in
  964.        IM2 mode */
  965.     if(sna.i==0x3f)
  966.         sna.im=0x01; 
  967.     else
  968.         sna.im=0x02; 
  969.         
  970.     if((vga.im & 0x01) == 0)
  971.         sna.iff2=0x00;
  972.     else
  973.         sna.iff2=0xff;
  974.  
  975.     sp=256*vga.sph+vga.spl;
  976.     sp=sp-2;
  977.     addr=sp-0x4000;
  978.     image[addr]=vga.pcl;
  979.     image[addr+1]=vga.pch;
  980.         
  981.     sna.sph=sp/256;
  982.     sna.spl=sp%256;
  983. }
  984.  
  985. void RASN_raw_to_sna()
  986. {
  987.     unsigned int addr;
  988.     unsigned int sp;
  989.     unsigned int pc;
  990.  
  991.     pc=0x1bf4; /* entry of "next statement" */
  992.  
  993.     sna.f=0x99;
  994.     sna.a=0x5f;
  995.     sna.b=0x1f;
  996.     sna.c=0xf0;
  997.     sna.d=0x5d;
  998.     sna.e=0x0c;
  999.     sna.h=0x5d;
  1000.     sna.l=0x0e;
  1001.  
  1002.     sna.fax=0x44;
  1003.     sna.aax=0x00;
  1004.     sna.bax=0x18;
  1005.     sna.cax=0x20;
  1006.     sna.dax=0x00;
  1007.     sna.eax=0x07;
  1008.     sna.hax=0x5c;
  1009.     sna.lax=0xf1;
  1010.  
  1011.     sna.ixh=0x03;
  1012.     sna.ixl=0xd4;
  1013.     sna.iyh=0x5c;
  1014.     sna.iyl=0x3a;
  1015.  
  1016.     sna.i=0x3f;
  1017.     sna.r=0x00;
  1018.     sna.im=0x01;
  1019.     sna.iff2=0xFF;
  1020.  
  1021.     /* set sp by means of RAMTOP in the image */
  1022.     addr=0x5cb2-0x4000;
  1023.     sp=256*image[addr+1]+image[addr]-1;
  1024.  
  1025.     /* Reset ERR NR to no error */
  1026.     image[0x5c3a-0x4000]=0xff;
  1027.     
  1028.     /* Set border by means of BORDCR */
  1029.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1030.     
  1031.     /* put return address to MAIN-4 (0x1303) on stack */
  1032.     sp=sp-2;
  1033.     addr=sp-0x4000;    
  1034.     image[addr]=0x03; 
  1035.     image[addr+1]=0x13;
  1036.     
  1037.     sp=sp-2;
  1038.     addr=sp-0x4000;
  1039.     image[addr]=pc%256;
  1040.     image[addr+1]=pc/256;
  1041.  
  1042.     sna.sph=sp/256;
  1043.     sna.spl=sp%256;
  1044. }
  1045.  
  1046. void Z8SN_z80_to_sna()
  1047. {
  1048.     unsigned int addr;
  1049.     unsigned int sp;
  1050.  
  1051.     sna.f=z80.f;
  1052.     sna.a=z80.a;
  1053.     sna.b=z80.b;
  1054.     sna.c=z80.c;
  1055.     sna.d=z80.d;
  1056.     sna.e=z80.e;
  1057.     sna.h=z80.h;
  1058.     sna.l=z80.l;
  1059.  
  1060.     sna.fax=z80.fax;
  1061.     sna.aax=z80.aax;
  1062.     sna.bax=z80.bax;
  1063.     sna.cax=z80.cax;
  1064.     sna.dax=z80.dax;
  1065.     sna.eax=z80.eax;
  1066.     sna.hax=z80.hax;
  1067.     sna.lax=z80.lax;
  1068.  
  1069.     sna.ixh=z80.ixh;
  1070.     sna.ixl=z80.ixl;
  1071.     sna.iyh=z80.iyh;
  1072.     sna.iyl=z80.iyl;
  1073.  
  1074.     sna.border=(z80.data/2) & 0x07; 
  1075.  
  1076.     sna.i=z80.i;
  1077.  
  1078.     if(z80.data==0xff) z80.data=0;
  1079.  
  1080.     if((z80.data & 0x01)==1)
  1081.         sna.r=(z80.r & 0x7f)+0x80;
  1082.     else
  1083.         sna.r=z80.r & 0x7f;
  1084.  
  1085.     sna.im=z80.im & 0x03;
  1086.     
  1087.     if(z80.iff2 != 0)
  1088.         sna.iff2=0xff;
  1089.     else
  1090.         sna.iff2=0x00;
  1091.  
  1092.     sp=256*z80.sph+z80.spl;
  1093.     sp=sp-2;
  1094.     addr=sp-0x4000;
  1095.         
  1096.     sna.sph=sp/256;
  1097.     sna.spl=sp%256;
  1098.  
  1099.     image[addr]=z80.pcl;
  1100.     image[addr+1]=z80.pch;
  1101. }
  1102.  
  1103. void PRSN_prg_to_sna()
  1104. {
  1105.     unsigned int addr;
  1106.     unsigned int sp;
  1107.  
  1108.     sna.b=prg.b;
  1109.     sna.c=prg.c;
  1110.     sna.d=prg.d;
  1111.     sna.e=prg.e;
  1112.     sna.h=prg.h;
  1113.     sna.l=prg.l;
  1114.     sna.fax=prg.fax;
  1115.     sna.aax=prg.aax;
  1116.     sna.bax=prg.bax;
  1117.     sna.cax=prg.cax;
  1118.     sna.dax=prg.dax;
  1119.     sna.eax=prg.eax;
  1120.     sna.hax=prg.hax;
  1121.     sna.lax=prg.lax;
  1122.  
  1123.     sna.ixh=prg.ixh;
  1124.     sna.ixl=prg.ixl;
  1125.     sna.iyh=prg.iyh;
  1126.     sna.iyl=prg.iyl;
  1127.  
  1128.     /* Set border by means of BORDCR */
  1129.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1130.  
  1131.     sna.i=prg.i;
  1132.  
  1133.     if(prg.i==0x3f)
  1134.         sna.im=0x01;
  1135.     else
  1136.         sna.im=0x02;
  1137.  
  1138.     sp=256*prg.sph+prg.spl;
  1139.     sp=sp+4; /* there are two more words on the stack besides PC */
  1140.     addr=sp-0x4000;
  1141.  
  1142.     sna.r=image[addr-3];
  1143.     /* the af combo is on the stack */
  1144.     sna.f=image[addr-2];
  1145.     sna.a=image[addr-1];
  1146.         
  1147.     sna.sph=sp/256;
  1148.     sna.spl=sp%256;
  1149.  
  1150.     /* interrupts always on ??? */
  1151.     sna.iff2=prg.iff2;
  1152. }
  1153.  
  1154. void ACSN_ach_to_sna()
  1155. {
  1156.     unsigned int addr;
  1157.     unsigned int sp;
  1158.  
  1159.     sna.f=ach.f;
  1160.     sna.a=ach.a;
  1161.     sna.b=ach.b;
  1162.     sna.c=ach.c;
  1163.     sna.d=ach.d;
  1164.     sna.e=ach.e;
  1165.     sna.h=ach.h;
  1166.     sna.l=ach.l;
  1167.  
  1168.     sna.fax=ach.fax;
  1169.     sna.aax=ach.aax;
  1170.     sna.bax=ach.bax;
  1171.     sna.cax=ach.cax;
  1172.     sna.dax=ach.dax;
  1173.     sna.eax=ach.eax;
  1174.     sna.hax=ach.hax;
  1175.     sna.lax=ach.lax;
  1176.  
  1177.     sna.ixh=ach.ixh;
  1178.     sna.ixl=ach.ixl;
  1179.     sna.iyh=ach.iyh;
  1180.     sna.iyl=ach.iyl;
  1181.  
  1182.     sna.border=ach.border;
  1183.  
  1184.     sna.i=ach.i;
  1185.  
  1186.     sna.r=ach.r;
  1187.  
  1188.     sna.im=ach.im & 0x03; 
  1189.     if(sna.im == 3)
  1190.          sna.im = 0;
  1191.         
  1192.     sna.iff2=ach.iff2;
  1193.  
  1194.     sp=256*ach.sph+ach.spl;
  1195.     sp=sp-2;
  1196.     addr=sp-0x4000;
  1197.         
  1198.     sna.sph=sp/256;
  1199.     sna.spl=sp%256;
  1200.  
  1201.     image[addr]=ach.pcl;
  1202.     image[addr+1]=ach.pch;
  1203. }
  1204.  
  1205. void KGSN_kgb_to_sna()
  1206. {
  1207.     unsigned int addr;
  1208.     unsigned int sp;
  1209.  
  1210.     sna.f=kgb.f;
  1211.     sna.a=kgb.a;
  1212.     sna.b=kgb.b;
  1213.     sna.c=kgb.c;
  1214.     sna.d=kgb.d;
  1215.     sna.e=kgb.e;
  1216.     sna.h=kgb.h;
  1217.     sna.l=kgb.l;
  1218.  
  1219.     sna.fax=kgb.fax;
  1220.     sna.aax=kgb.aax;
  1221.     sna.bax=kgb.bax;
  1222.     sna.cax=kgb.cax;
  1223.     sna.dax=kgb.dax;
  1224.     sna.eax=kgb.eax;
  1225.     sna.hax=kgb.hax;
  1226.     sna.lax=kgb.lax;
  1227.  
  1228.     sna.ixh=kgb.ixh;
  1229.     sna.ixl=kgb.ixl;
  1230.     sna.iyh=kgb.iyh;
  1231.     sna.iyl=kgb.iyl;
  1232.  
  1233.     sna.i=kgb.i;
  1234.     sna.r=kgb.r;
  1235.  
  1236.     /* border-colour not found in KGB image */
  1237.     /* Set border by means of BORDCR */
  1238.     sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
  1239.  
  1240.     /* determine interrupt mode using the value of register I */
  1241.     if (kgb.i_mode_l==0xff)
  1242.         sna.im=0x00;
  1243.     else if(kgb.i_mode_l==1)
  1244.         sna.im=0x02; 
  1245.     else
  1246.         sna.im=0x01;
  1247.         
  1248.     if((kgb.interruptstatus & 0x01) != 0)
  1249.         sna.iff2=0xff;
  1250.     else
  1251.         sna.iff2=0x0;
  1252.  
  1253.     sp=256*kgb.sph+kgb.spl;
  1254.     sp=sp-2;
  1255.     addr=sp-0x4000;
  1256.         
  1257.     sna.sph=sp/256;
  1258.     sna.spl=sp%256;
  1259.  
  1260.     image[addr]=kgb.pcl;
  1261.     image[addr+1]=kgb.pch;
  1262. }
  1263.  
  1264. /* CONVERSION FUNCTIONS - FROM .SNA FORMAT */
  1265.  
  1266. void SNVG_sna_to_vgaspec()
  1267. {
  1268.     unsigned int addr;
  1269.     unsigned int sp;
  1270.     unsigned int pc;
  1271.  
  1272.     sp=256*sna.sph+sna.spl;
  1273.     addr=sp-0x4000;
  1274.     pc=image[addr]+256*image[addr+1];
  1275.     sp=sp+2;
  1276.  
  1277.     vga.S='S';
  1278.     vga.P='P';
  1279.     vga.len_l=0x00;
  1280.     vga.len_h=0xC0;
  1281.     vga.start_l=0x00;
  1282.     vga.start_h=0x40;
  1283.     vga.f=sna.f;
  1284.     vga.a=sna.a;
  1285.     vga.b=sna.b;
  1286.     vga.c=sna.c;
  1287.     vga.d=sna.d;
  1288.     vga.e=sna.e;
  1289.     vga.h=sna.h;
  1290.     vga.l=sna.l;
  1291.  
  1292.     vga.fax=sna.fax;
  1293.     vga.aax=sna.aax;
  1294.     vga.bax=sna.bax;
  1295.     vga.cax=sna.cax;
  1296.     vga.dax=sna.dax;
  1297.     vga.eax=sna.eax;
  1298.     vga.hax=sna.hax;
  1299.     vga.lax=sna.lax;
  1300.  
  1301.     vga.ixh=sna.ixh;
  1302.     vga.ixl=sna.ixl;
  1303.     vga.iyh=sna.iyh;
  1304.     vga.iyl=sna.iyl;
  1305.  
  1306.     vga.i=sna.i;
  1307.     vga.r=sna.r;
  1308.  
  1309.     vga.im=sna.im & 0x02; /* 0 for IM1, 2 for IM2 */
  1310.  
  1311.     /* works? how does it know it was IM1 ? */
  1312.     if((sna.iff2 & 0x04) != 0)
  1313.         vga.im=vga.im | 0x01; 
  1314.  
  1315.     vga.sph=sp/256;
  1316.     vga.spl=sp%256;
  1317.     
  1318.     vga.pch=pc/256;
  1319.     vga.pcl=pc%256;
  1320.  
  1321.     vga.border=sna.border; 
  1322.  
  1323.     vga.res2=0;
  1324.     vga.res3=0;
  1325.     vga.res4=0;
  1326.     vga.res5=0;
  1327. }
  1328.  
  1329. void SNZ8_sna_to_z80()
  1330. {
  1331.     unsigned int addr;
  1332.     unsigned int sp;
  1333.     unsigned int pc;
  1334.  
  1335.     sp=256*sna.sph+sna.spl;
  1336.     addr=sp-0x4000;
  1337.     pc=image[addr]+256*image[addr+1];
  1338.     sp=sp+2;
  1339.  
  1340.     z80.f=sna.f;
  1341.     z80.a=sna.a;
  1342.     z80.b=sna.b;
  1343.     z80.c=sna.c;
  1344.     z80.d=sna.d;
  1345.     z80.e=sna.e;
  1346.     z80.h=sna.h;
  1347.     z80.l=sna.l;
  1348.  
  1349.     z80.fax=sna.fax;
  1350.     z80.aax=sna.aax;
  1351.     z80.bax=sna.bax;
  1352.     z80.cax=sna.cax;
  1353.     z80.dax=sna.dax;
  1354.     z80.eax=sna.eax;
  1355.     z80.hax=sna.hax;
  1356.     z80.lax=sna.lax;
  1357.  
  1358.     z80.ixh=sna.ixh;
  1359.     z80.ixl=sna.ixl;
  1360.     z80.iyh=sna.iyh;
  1361.     z80.iyl=sna.iyl;
  1362.  
  1363.     z80.i=sna.i;
  1364.     z80.r=sna.r | 0x080; /* bit 7 is stored somewhere else, always set */
  1365.     z80.im=sna.im & 0x03;
  1366.     z80.im=z80.im + 0x60; /* fixed normal video/kempston joystick */
  1367.  
  1368.     z80.sph=sp/256;
  1369.     z80.spl=sp%256;
  1370.     
  1371.     z80.pch=pc/256;
  1372.     z80.pcl=pc%256;
  1373.  
  1374.     /* all kinds of stuff put in "data" */
  1375.     z80.data=(sna.border & 0x07)*2; 
  1376.     if((sna.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
  1377.  
  1378.     /* image is not compressed, compression will be done by the */
  1379.     /* z80_write function.                                      */
  1380.     z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
  1381.  
  1382.     if((sna.iff2 & 0x04) != 0) {
  1383.         z80.iff1=0xff;
  1384.         z80.iff2=0xff;
  1385.     } else {
  1386.         z80.iff1=0;
  1387.         z80.iff2=0;
  1388.     }
  1389. }
  1390.  
  1391. void SNPR_sna_to_prg(char * n)
  1392. {
  1393.     unsigned int addr;
  1394.     unsigned int sp;
  1395.     int i;
  1396.     unsigned char * p;
  1397.  
  1398.     /* clean header structure first */
  1399.     p=(unsigned char *) &prg;
  1400.     for(i=0; i < 256; i++)
  1401.         p[i]='\0';
  1402.  
  1403.     prg.c_0x61=0x61; /* size of image in sectors */
  1404.     prg.c_0x35=0x35; /* don't know yet */
  1405.     prg.c_0x03=0x03; /* don't know yet */
  1406.  
  1407.     sp=256*sna.sph+sna.spl;
  1408.     addr=sp-0x4000;
  1409.  
  1410.     /* these are on the stack */
  1411.     image[addr-1]=sna.a;
  1412.     image[addr-2]=sna.f;
  1413.     image[addr-3]=sna.r;
  1414.     image[addr-4]=sna.iff2;
  1415.  
  1416.     sp=sp-4;
  1417.  
  1418.     prg.name[0]='\0';
  1419.     strncpy(prg.name,n,10);
  1420.     prg.name[10]='\0';
  1421.  
  1422.     prg.b=sna.b;
  1423.     prg.c=sna.c;
  1424.     prg.d=sna.d;
  1425.     prg.e=sna.e;
  1426.     prg.h=sna.h;
  1427.     prg.l=sna.l;
  1428.  
  1429.     prg.fax=sna.fax;
  1430.     prg.aax=sna.aax;
  1431.     prg.bax=sna.bax;
  1432.     prg.cax=sna.cax;
  1433.     prg.dax=sna.dax;
  1434.     prg.eax=sna.eax;
  1435.     prg.hax=sna.hax;
  1436.     prg.lax=sna.lax;
  1437.  
  1438.     prg.ixh=sna.ixh;
  1439.     prg.ixl=sna.ixl;
  1440.     prg.iyh=sna.iyh;
  1441.     prg.iyl=sna.iyl;
  1442.  
  1443.     prg.i=sna.i;
  1444.     prg.iff2=sna.iff2;
  1445.  
  1446.     prg.sph=sp/256;
  1447.     prg.spl=sp%256;
  1448.     
  1449.     /* prg.border=sna.border; */
  1450. }
  1451.  
  1452. void SNAC_sna_to_ach()
  1453. {
  1454.     unsigned int addr;
  1455.     unsigned int sp;
  1456.     unsigned int pc;
  1457.     int i;
  1458.     unsigned char * p;
  1459.  
  1460.     /* clean header structure first */
  1461.     p=(unsigned char *) &ach;
  1462.     for(i=0; i < 256; i++)
  1463.         p[i]='\0';
  1464.  
  1465.     sp=256*sna.sph+sna.spl;
  1466.     addr=sp-0x4000;
  1467.     pc=image[addr]+256*image[addr+1];
  1468.     sp=sp+2;
  1469.  
  1470.     ach.f=sna.f;
  1471.     ach.a=sna.a;
  1472.     ach.b=sna.b;
  1473.     ach.c=sna.c;
  1474.     ach.d=sna.d;
  1475.     ach.e=sna.e;
  1476.     ach.h=sna.h;
  1477.     ach.l=sna.l;
  1478.  
  1479.     ach.fax=sna.fax;
  1480.     ach.aax=sna.aax;
  1481.     ach.bax=sna.bax;
  1482.     ach.cax=sna.cax;
  1483.     ach.dax=sna.dax;
  1484.     ach.eax=sna.eax;
  1485.     ach.hax=sna.hax;
  1486.     ach.lax=sna.lax;
  1487.  
  1488.     ach.ixh=sna.ixh;
  1489.     ach.ixl=sna.ixl;
  1490.     ach.iyh=sna.iyh;
  1491.     ach.iyl=sna.iyl;
  1492.  
  1493.     ach.i=sna.i;
  1494.     ach.r=sna.r;
  1495.  
  1496.     ach.border=sna.border;
  1497.  
  1498.     if((sna.iff2 & 0x04) != 0)
  1499.         ach.iff2=0xff;
  1500.     else
  1501.         ach.iff2=0x00;
  1502.  
  1503.     ach.im=sna.im;
  1504.  
  1505.     ach.sph=sp/256;
  1506.     ach.spl=sp%256;
  1507.     
  1508.     ach.pch=pc/256;
  1509.     ach.pcl=pc%256;
  1510. }
  1511.  
  1512. void SNKG_sna_to_kgb()
  1513. {
  1514.     unsigned int addr;
  1515.     unsigned int sp;
  1516.     unsigned int pc;
  1517.     int i;
  1518.     unsigned char * p;
  1519.  
  1520.     /* clean info structure first */
  1521.     p = (unsigned char *) &kgb;
  1522.     for(i=0; i < 202; i++)
  1523.         p[i]='\0';
  1524.  
  1525.     /* make some assumptions here */
  1526.     kgb.is3_1 = 3;        /* always 3, don't ask me why */
  1527.     kgb.colourmode = 1;    /* assume colour */
  1528.     kgb.soundmode = 1;    /* assume simple sound */
  1529.     kgb.haltmode = 1;    /* assume not in halt mode */
  1530.  
  1531.     sp=256*sna.sph+sna.spl;
  1532.     addr=sp-0x4000;
  1533.     pc=image[addr]+256*image[addr+1];
  1534.     sp=sp+2;
  1535.  
  1536.     kgb.f=sna.f;
  1537.     kgb.a=sna.a;
  1538.     kgb.b=sna.b;
  1539.     kgb.c=sna.c;
  1540.     kgb.d=sna.d;
  1541.     kgb.e=sna.e;
  1542.     kgb.h=sna.h;
  1543.     kgb.l=sna.l;
  1544.  
  1545.     kgb.fax=sna.fax;
  1546.     kgb.aax=sna.aax;
  1547.     kgb.bax=sna.bax;
  1548.     kgb.cax=sna.cax;
  1549.     kgb.dax=sna.dax;
  1550.     kgb.eax=sna.eax;
  1551.     kgb.hax=sna.hax;
  1552.     kgb.lax=sna.lax;
  1553.  
  1554.     kgb.ixh=sna.ixh;
  1555.     kgb.ixl=sna.ixl;
  1556.     kgb.iyh=sna.iyh;
  1557.     kgb.iyl=sna.iyl;
  1558.  
  1559.     kgb.i=sna.i;
  1560.  
  1561.     kgb.r=sna.r;
  1562.  
  1563.     /* kgb.border=sna.border; NOT IN KGB IMAGE! */
  1564.  
  1565.     /* Interupt mode is stored in a word in the KGB format. */
  1566.     /* Use byte accesses to be CPU independent              */
  1567.  
  1568.     switch (sna.im & 0x03) {
  1569.     case 0:    kgb.i_mode_h = 0xff;
  1570.         kgb.i_mode_l = 0xff;
  1571.         break;
  1572.     case 2: kgb.i_mode_h = 0;
  1573.         kgb.i_mode_l = 1;
  1574.         break;
  1575.     default:kgb.i_mode_h = 0;
  1576.         kgb.i_mode_l = 0;
  1577.         break;
  1578.     }
  1579.  
  1580.     if((sna.iff2 & 0x04) != 0)
  1581.         kgb.interruptstatus=0x01;
  1582.     else
  1583.         kgb.interruptstatus=0x00;
  1584.  
  1585.     kgb.sph=sp/256;
  1586.     kgb.spl=sp%256;
  1587.     
  1588.     kgb.pch=pc/256;
  1589.     kgb.pcl=pc%256;
  1590. }
  1591.  
  1592. /* 16K PAGE READ FUNCTION FOR .Z80 FORMAT */
  1593.  
  1594. /*
  1595.  * Function returns:
  1596.  *      0: No more pages
  1597.  *    1: Page read
  1598.  */
  1599. int RDPG_z80_read_page(char * s, FILE * fd)
  1600. {
  1601.     struct    z80_page_s page_info;
  1602.     unsigned int    len;
  1603.     unsigned int    pos;
  1604.     long        f_len;
  1605.  
  1606.     if(fread(&page_info,z80_pg_size,1,fd)!=1)    {
  1607.         return 0;
  1608.     }
  1609.     len = (256 * page_info.blklen_h) + page_info.blklen_l;
  1610.  
  1611.     switch(page_info.page_num) {
  1612.     case 0:    fprintf(stderr,"%s - memory page 0 - 48K rom ignored\n",s);
  1613.         pos=0x0ffff;
  1614.         break;
  1615.     case 1:    fprintf(stderr,"%s - memory page 1 - Interface 1 rom ignored\n",s);
  1616.         pos=0x0ffff;
  1617.         break;
  1618.     case 2:    fprintf(stderr,"%s - memory page 2 - basic samram rom ignored\n",s);
  1619.         pos=0x0ffff;
  1620.         break;
  1621.     case 3:    fprintf(stderr,"%s - memory page 3 - monitor samram rom ignored\n",s);
  1622.         pos=0x0ffff;
  1623.         break;
  1624.     case 4:    pos=0x04000;    /* second 16K of RAM area */
  1625.         break;
  1626.     case 5:    pos=0x08000;    /* third 16K of RAM area */
  1627.         break;
  1628.     case 6:    fprintf(stderr,"%s - memory page 6 - shadow rom 8000-BFFF ignored\n",s);
  1629.         pos=0x0ffff;
  1630.         break;
  1631.     case 7:    fprintf(stderr,"%s - memory page 7 - shadow rom C000-FFFF ignored\n",s);
  1632.         pos=0x0ffff;
  1633.         break;
  1634.     case 8:    pos=0;        /* first 16K of RAM area */
  1635.         break;
  1636.     case 9:    fprintf(stderr,"%s - memory page 8 - 128K page 6 ignored\n",s);
  1637.         pos=0x0ffff;
  1638.         break;
  1639.     case 10:fprintf(stderr,"%s - memory page 10 - 128K page7 ignored\n",s);
  1640.         pos=0x0ffff;
  1641.         break;
  1642.     default:fprintf(stderr,"%s - memory page %d - Invalid page number -fatal-\n",s,page_info.page_num);
  1643.         exit(EXIT_FILE_ERROR);
  1644.         break;
  1645.     }
  1646.  
  1647.     if(pos == (unsigned int) 0x0ffff) {
  1648.         /* wrong page, seek over this page */
  1649.         if(fseek(fd, (long) len, SEEK_CUR)!=0)
  1650.             RERR_read_error(s, fd);
  1651.     } else {
  1652.         /* Valid 48K page, read and decompress */
  1653.  
  1654.         f_len = 0 - ftell(fd);
  1655.         Z80D_z80_decompress(fd, pos, 16384);
  1656.         f_len = f_len + ftell(fd);
  1657.  
  1658.         if((long) len != f_len) {
  1659.             fprintf(stderr,"Z80 image corrupted, can't convert\n");
  1660.             fclose(fd);
  1661.             exit(EXIT_FILE_ERROR);
  1662.         }
  1663.     }
  1664.     return 1;
  1665. }
  1666.  
  1667. /* COMPRESSION/DECOMPRESSION for .Z80 FORMAT */
  1668.  
  1669. void Z80D_z80_decompress(FILE * fd, unsigned int start, unsigned int imsize)
  1670. {
  1671.     int          c,j,k;
  1672.     unsigned char l;
  1673.     unsigned char im;
  1674.  
  1675.     j=start;
  1676.     while(j<(start+imsize)) {
  1677.         c=getc(fd);
  1678.         if(c == -1) return;
  1679.         im = (unsigned char) c;
  1680.  
  1681.         if(im!=0xed) {
  1682.             image[j++]=im;
  1683.         } else {
  1684.             c=getc(fd);
  1685.             if(c == -1) return;
  1686.             im = (unsigned char) c;
  1687.             if(im!=0xed) {
  1688.                 image[j++]=0xed;
  1689.                 ungetc(im,fd);
  1690.             } else {
  1691.                 /* fetch count */
  1692.                 k=getc(fd);
  1693.                 if(k == -1) return;
  1694.                 /* fetch character */
  1695.                 c=getc(fd);
  1696.                 if(c == -1) return;
  1697.                 l = (unsigned char) c;
  1698.                 while(k!=0) {
  1699.                     image[j++]=l;
  1700.                     k--;
  1701.                 }
  1702.             }
  1703.         }
  1704.     }
  1705.  
  1706.     if(j!=(start+imsize)) {
  1707.         fprintf(stderr,"Z80 image corrupted, can't decompress\n");
  1708.         exit(EXIT_FILE_ERROR);
  1709.     }
  1710. }
  1711.  
  1712. int Z80C_z80_compress()
  1713. {
  1714. #ifdef __TURBOC__
  1715.     unsigned char far * comp;
  1716. #else
  1717.     unsigned char * comp;
  1718. #endif
  1719.     unsigned int i,j;
  1720.     unsigned int num;
  1721.     unsigned char c,n;
  1722.     unsigned int ed;
  1723.  
  1724.     z80_size=(unsigned int) IMSIZE;
  1725.  
  1726.     /*
  1727.      * We need an intermediate buffer here, if the compressed image
  1728.      * is bigger than the uncompressed image than the image will
  1729.      * not be compressed to save space (!)
  1730.      */
  1731.  
  1732. #ifdef __TURBOC__
  1733.     comp=(unsigned char far *) farmalloc((unsigned long)(IMSIZE+0x0100));
  1734. #else
  1735.     comp=(unsigned char *) malloc((size_t)(IMSIZE+0x0100));
  1736. #endif
  1737.     if(comp==NULL) {
  1738.         printf("Warning: Not enough memory to compress the image, using uncopressed image\n");
  1739.         return NOTCOMPRESSED;
  1740.     }
  1741.  
  1742.     i=0;
  1743.     j=0;
  1744.     /* ensure 'ed' is not set */
  1745.     ed=NO;
  1746.     while(i<IMSIZE)    {
  1747.         c=image[i];
  1748.         i++;
  1749.         if(i<IMSIZE) {
  1750.             n=image[i];
  1751.         } else {
  1752.             /* force 'n' to be unequal to 'c' */
  1753.             n=c;
  1754.             n++;
  1755.         }
  1756.  
  1757.         if(c!=n) {
  1758.             comp[j]=c;
  1759.             j++;
  1760.             if(c==0xed) 
  1761.                 ed=YES;
  1762.             else
  1763.                 ed=NO;
  1764.         } else {
  1765.             if(c==0xed) {
  1766.                 /* two times 0xed - special care */
  1767.                 comp[j]=0xed;
  1768.                 j++;
  1769.                 comp[j]=0xed;
  1770.                 j++;
  1771.                 comp[j]=0x02;
  1772.                 j++;
  1773.                 comp[j]=0xed;
  1774.                 j++;
  1775.                 i++; /* skip second ED */
  1776.  
  1777.                 /* because 0xed is valid compressed we don't
  1778.                    have to watch it! */
  1779.                 ed=NO;
  1780.             } else if(ed==YES) {
  1781.                 /* can't compress now, skip this double pair */
  1782.                 comp[j]=c;
  1783.                 j++;
  1784.                 ed=NO;    /* 'c' can't be 0xed */
  1785.             } else {
  1786.                 num=1;
  1787.                 while(i<IMSIZE) {
  1788.                     if(c!=image[i])
  1789.                         break;
  1790.                     num++;
  1791.                     i++;
  1792.                     if(num==255)
  1793.                         break;
  1794.                 }
  1795.                 if(num <= 4) {
  1796.                     /* no use to compress */
  1797.                     while(num!=0) {
  1798.                         comp[j]=c;
  1799.                         j++;
  1800.                         num--;
  1801.                     }
  1802.                 } else {
  1803.                     comp[j]=0xed;
  1804.                     j++;
  1805.                     comp[j]=0xed;
  1806.                     j++;
  1807.                     comp[j]=(unsigned char) num;
  1808.                     j++;
  1809.                     comp[j]=c;
  1810.                     j++;
  1811.                 }
  1812.             }
  1813.         }
  1814.  
  1815.         if(j >= (IMSIZE-4)) {
  1816.             /* compressed image bigger or same than original */
  1817. #ifdef __TURBOC__
  1818.             farfree((void far *) comp);
  1819. #else
  1820.             free((void *) comp);
  1821. #endif
  1822.             return NOTCOMPRESSED;
  1823.         }
  1824.     }
  1825.     /* append "end of compressed area" mark */
  1826.     comp[j]=0;
  1827.     j++;
  1828.     comp[j]=0xed;
  1829.     j++;
  1830.     comp[j]=0xed;
  1831.     j++;
  1832.     comp[j]=0;
  1833.     j++;
  1834.  
  1835.     z80_size = j;
  1836.     
  1837.     /* copy back */
  1838.     i=0;
  1839.     j=0;
  1840.     while(i<IMSIZE)
  1841.         image[i++]=comp[j++];
  1842. #ifdef __TURBOC__
  1843.     farfree((void far *) comp);
  1844. #else
  1845.     free((void *) comp);
  1846. #endif
  1847.     return COMPRESSED;
  1848. }
  1849.