home *** CD-ROM | disk | FTP | other *** search
Text File | 1994-06-27 | 38.1 KB | 1,849 lines |
- /*
- * SPCONV - ZX-Spectrum 48K snapshot converter
- *
- * Public Domain software
- *
- * Author: Henk de Groot
- */
-
- #if defined(__STDC__) || defined(__TURBOC__)
- #include <stdlib.h>
- #else
- #include <sys/types.h>
- #endif
-
- #ifdef __TURBOC__
- #include <io.h>
- #else
- #include <unistd.h>
- #endif
-
- #include <stdio.h>
- #include <fcntl.h>
- #include <sys/stat.h>
- #include <string.h>
- #include <ctype.h>
- /* #ifdef __TURBOC__
- #include <alloc.h>
- #else
- #include <malloc.h>
- #endif */
-
- #ifndef O_BINARY
- #define O_BINARY 0
- #endif
-
- #include "spconv.h"
-
- struct sna_s sna;
- struct vga_s vga;
- struct z80_s z80;
- struct prg_s prg;
- struct ach_s ach;
- struct kgb_s kgb;
-
- /* extra space just in case the Z80 decompress fails due to a corrupt image */
- unsigned char image[IMSIZE+0x100];
- unsigned int z80_size;
-
- int intype;
- int outtype;
-
- /* Path names are limited to 80 characters under MSDOS so this sould be */
- /* enough... If you are using UNIX than you may have to make this array */
- /* larger. */
- char my_directory[120];
-
- int main(int argc,char *argv[])
- {
- char *p;
- struct stat status;
- const char * fromstring;
- const char * tostring;
- char * outfile;
- long file_size;
-
- #ifdef __TURBOC__
- /* for Trubo-C: open all files in binary mode */
- extern int _fmode;
- _fmode = O_BINARY;
- #endif
-
- if(argc != 3)
- USAG_usage();
-
- if((strchr(argv[1],'*')!=NULL) || (strrchr(argv[1],'?')!=NULL) ||
- (strchr(argv[2],'*')!=NULL) || (strrchr(argv[2],'?')!=NULL)) {
- fprintf(stderr,"This program can't handle wildcards, sorry!\n");
- return EXIT_USAGE;
- }
-
- /*
- * Find the directory path where this program is started from.
- * This will be needed for finding the spectrum-rom. Some formats
- * need the spectrum-rom for proper conversion.
- */
- strcpy(my_directory,argv[0]);
- if(strrchr(my_directory,'\\')!=NULL) {
- *strrchr(my_directory,'\\')='\0';
- }
- else if(strrchr(my_directory,'/')!=NULL) {
- *strrchr(my_directory,'/')='\0';
- }
- else if(strrchr(my_directory,':')!=NULL) {
- *strrchr(my_directory,':')='\0';
- } else {
- my_directory[0]='\\';
- my_directory[1]='\0';
- }
-
- /*
- * Check if the input file exists and fetch the file lenght of
- * the file in the mean time. Two for the prise of one...
- */
- if(stat(argv[1],&status)<0) {
- perror(argv[1]);
- return EXIT_FILE_ERROR;
- }
- file_size = status.st_size;
-
- /*
- * recognize input type on filename:
- *
- * .SNA -> SNA file (used in JPP)
- * .SP -> SP file (was VGASPEC)
- * .Z80 -> Z80 file
- * .PRG -> PRG file
- * .ACH -> ACH file (from archimedes emulator)
- * .ZX -> KGB file (from KGB emulator)
- * other -> if exact 48+header -> raw file
- * otherwise unknown
- */
-
- fromstring = DTYP_determine_type(argv[1],&intype);
-
- if (intype == UNKNOWN) {
- if (file_size == (hdr_size+IMSIZE)) {
- fromstring="RAW";
- intype=RAW;
- } else {
- fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH or\n");
- fprintf(stderr,".ZX file, or a Raw file\n");
- return EXIT_FILE_ERROR;
- }
- }
-
- /*
- * recognize output type on filename:
- *
- * .SNA -> SNA file
- * .SP -> SP file (was VGASPEC)
- * .Z80 -> Z80 file
- * .PRG -> PRG file
- * .ACH -> ACH file (from archimedes emulator)
- * .ZX -> KGB file (from KGB emulator)
- * otherwise unknown
- */
-
- tostring = DTYP_determine_type(argv[2],&outtype);
-
- if(outtype==UNKNOWN) {
- fprintf(stderr,"Unknown output file format. Must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file\n");
- return EXIT_FILE_ERROR;
- }
-
- /*
- * if argv[2] only contains the suffix then use the prefix of
- * argv[1];
- */
- if(argv[2][0]=='.') {
- outfile=malloc(strlen(argv[1])+strlen(argv[2])+1);
- strcpy(outfile,argv[1]); /* copy prefix */
-
- p=strrchr(outfile,'.');
- if(p!=NULL) *p='\0'; /* put end of string at position of '.' */
-
- strcat(outfile,argv[2]); /* append suffix */
- } else {
- outfile=malloc(strlen(argv[2])+1);
-
- strcpy(outfile,argv[2]);
- }
-
- /*
- * Special converion between versions of the same type
- */
- if(intype == outtype)
- return DIRC_direct_convert(intype, argv[1], outfile);
-
- /*
- * General conversion from one type to another
- */
-
- printf("Converting %s from %s to %s\n",argv[1],fromstring,tostring);
-
- /*
- * convert input_file to SNA
- */
-
- switch(intype) {
- case SNA: if (file_size == (sna_size+IMSIZE)) {
- RSNA_read_sna(argv[1]);
- }
- break;
- case SP: if ((file_size == (vga_size+IMSIZE))) {
- RVGA_read_vgaspec(argv[1]);
- VGSN_vgaspec_to_sna();
- } else if ((file_size == (vga_size+IMSIZE-6))) {
- ROVG_read_old_vgaspec(argv[1]);
- VGSN_vgaspec_to_sna();
- }
- break;
- case RAW: RRAW_read_raw(argv[1]);
- RASN_raw_to_sna();
- break;
- case Z80: RZ80_read_z80(argv[1]);
- Z8SN_z80_to_sna();
- break;
- case PRG: if(file_size != (prg_size+IMSIZE)) {
- printf("Warning: the image part of %s is not exactly 48k!\n",argv[1]);
- printf(" Converting anyway, the converted file may not work\n");
- }
- RPRG_read_prg(argv[1]);
- PRSN_prg_to_sna();
- break;
- case ACH: if(file_size == (ach_size+16384L+IMSIZE)) {
- RACH_read_ach(argv[1]);
- ACSN_ach_to_sna();
- }
- break;
- case KGB: if(file_size == (132L+IMSIZE+kgb_size)) {
- RKGB_read_kgb(argv[1]);
- KGSN_kgb_to_sna();
- }
- break;
- default: printf("Unrecognized input file type, can't convert\n");
- return EXIT_FILE_ERROR;
- }
-
- /*
- * convert internal SNA format to output file
- */
-
- switch(outtype) {
- case SNA: WSNA_write_sna(outfile);
- break;
- case SP: SNVG_sna_to_vgaspec();
- WVGA_write_vgaspec(outfile);
- break;
- case Z80: SNZ8_sna_to_z80();
- WZ80_write_z80(outfile);
- break;
- case PRG: SNPR_sna_to_prg(outfile);
- WPRG_write_prg(outfile);
- break;
- case ACH: SNAC_sna_to_ach();
- WACH_write_ach(outfile);
- break;
- case KGB: SNKG_sna_to_kgb();
- WKGB_write_kgb(outfile);
- break;
- default: printf("Unrecognized output file type, can't convert\n");
- return EXIT_FILE_ERROR;
- }
-
- /*
- * That's it, simple isn't it?
- */
- return EXIT_OK;
- }
-
- /* SPECIAL FUNCTIONS */
-
- /* Determine file type and return both type and type-name */
-
- const char * DTYP_determine_type(char * filename, int * type)
- {
- const char *p;
- char ext[5];
- int i;
-
- /*
- * recognize type on filename:
- *
- * .SNA -> SNA file
- * .SP -> SP file (was VGASPEC)
- * .Z80 -> Z80 file
- * .PRG -> PRG file
- * .ACH -> ACH file (from archimedes emulator)
- * .ZX -> KGB file (from KGB emulator)
- * otherwise unknown
- */
-
- *type=UNKNOWN; /* default if all ifs below fail */
-
- p=strrchr(filename,'.');
- if(p==NULL) p=filename; /* not found, set at begin of string */
-
- /* Take extension and convert to uppercase */
- for(i = 0; i < 4; i++) {
- if(*p != '\0') {
- ext[i] = toupper(*p);
- p++;
- } else {
- ext[i] = '\0';
- }
- }
- ext[4] = '\0'; /* termination at least on the fifth char */
-
- if(strcmp(ext,".SNA")==0) {
- *type=SNA;
- return ".SNA";
- }
- if(strcmp(ext,".Z80")==0) {
- *type=Z80;
- return ".Z80";
- }
- if(strcmp(ext,".SP")==0) {
- *type=SP;
- return ".SP";
- }
- if(strcmp(ext,".PRG")==0) {
- *type=PRG;
- return ".PRG";
- }
- if(strcmp(ext,".ACH")==0) {
- *type=ACH;
- return ".ACH";
- }
- if(strcmp(ext,".ZX")==0) {
- *type=KGB;
- return ".ZX";
- }
-
- /* unknown type, return question-mark */
- return "?";
- }
-
- /* Special converion between versions of the same type */
-
- int DIRC_direct_convert(int type, char * infile, char * outfile)
- {
- struct stat status;
- long file_size;
-
- /*
- * Special conversion between versions of the same type.
- * These conversion don't use the intermediate 'sna' format
- * to preserve as much information as possible.
- *
- * This currently only applies to .SP and the .Z80 formats.
- *
- * The .SP formats will convert from the New to the Old format or
- * from the Old to the New format, controled by the current format
- * of the input.
- *
- * The .Z80 formats will convert to the version 1.45 .Z80 format
- * since version 1.45 .Z80 files can be read by both old and new
- * Z80-emulators.
- */
-
- /* check if it is for the SP format */
- if(type == SP) {
- if(stat(infile,&status)<0) {
- perror(infile);
- return EXIT_FILE_ERROR;
- }
- file_size = status.st_size;
-
- if((file_size == (vga_size+IMSIZE))) {
- printf("Converting %s from new .SP format to old .SP format.\n",infile);
- RVGA_read_vgaspec(infile);
-
- WOVG_write_old_vgaspec(outfile);
- return EXIT_OK;
- }
-
- if((file_size == (vga_size+IMSIZE-6))) {
- RVGH_read_vgaspec_header(infile);
-
- if((vga.S=='S')&&(vga.P=='P')) {
- fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
- fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
- fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
- fprintf(stderr,"contain images of 48Kb length.\n");
- return EXIT_FILE_ERROR;
- }
-
- printf("Converting %s from old .SP format to new .SP format.\n",infile);
- ROVG_read_old_vgaspec(infile);
-
- /* These values are fixed for a full 48K .SP file */
- vga.S='S';
- vga.P='P';
- vga.len_l=0x00;
- vga.len_h=0xC0;
- vga.start_l=0x00;
- vga.start_h=0x40;
-
- WVGA_write_vgaspec(outfile);
-
- return EXIT_OK;
- } else {
- RVGH_read_vgaspec_header(infile);
- if((vga.S=='S')&&(vga.P=='P')) {
- fprintf(stderr,"Invalid input file format. This could be a new syle .SP file with\n");
- fprintf(stderr,"an image of another length than 48Kb. This kind of .SP files cannot\n");
- fprintf(stderr,"be converted. All other file formats (including the old .SP format)\n");
- fprintf(stderr,"contain images of 48Kb length.\n");
- } else {
- fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or RAW file\n");
- }
- return EXIT_FILE_ERROR;
- }
- }
-
- if(type == Z80)
- {
- printf("Converting %s from .Z80 to .Z80 (output in version 1.45 format)\n",infile);
- RZ80_read_z80(infile);
-
- WZ80_write_z80(outfile);
- return EXIT_OK;
- }
-
- /* If we get here than we had no special handling for this type */
- /* return an error in that case... */
- fprintf(stderr,"Input and output file format are the same. ");
- fprintf(stderr,"What you try to do\n");
- fprintf(stderr,"is handled much better by the MSDOS \"COPY\" ");
- fprintf(stderr,"command!\n");
-
- return EXIT_USAGE;
- }
-
- /* ERROR HANDLING FUNCTIONS */
-
- /* Print Usage and exit */
- void USAG_usage()
- {
- fprintf(stderr,"SPCONV version 1.07 - %s\n\n",__DATE__);
- fprintf(stderr,"Usage: spconv <source> <target>\n\n");
- fprintf(stderr,"Source must be a valid .SNA, .SP, .Z80, .PRG, .ACH, .ZX or RAW file.\n");
- fprintf(stderr,"Target must be a .SNA, .SP, .Z80, .PRG, .ACH or .ZX file.\n\n");
- fprintf(stderr,"If the second parameter contains only a suffix, the prefix\n");
- fprintf(stderr,"of the input file will be used (i.e. 'spconv file.sna .z80')\n\n");
- fprintf(stderr,"Output .SP files are in the new format, .Z80 files are compressed\n");
- fprintf(stderr,"in the version 1.45 .Z80 format\n\n");
- fprintf(stderr,"If <source> and <target> are .SP files, convertion from old\n");
- fprintf(stderr,"to new format or from new to old format will be performed.\n");
- fprintf(stderr,"If <source> and <target> are .Z80 files, convertion to\n");
- fprintf(stderr,"the version 1.45 format will be performed.\n");
- fprintf(stderr,"If <source> and <target> are of the same type an error message\n");
- fprintf(stderr,"will be generated (unless they are both .SP or .Z80 files)\n");
- fprintf(stderr,"\n\nPublic Domain, H. de Groot 1994\n\n");
-
- exit(EXIT_USAGE);
- }
-
- void RERR_read_error(char * s, FILE * fd)
- {
- perror(s);
- if(fd != NULL) fclose(fd);
- exit(EXIT_READ_ERROR);
- }
-
- void WERR_write_error(char * s, FILE * fd)
- {
- perror(s);
- if(fd != NULL) fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
-
- /* I/O FUNCTIONS */
-
- /* GENERIC I/O - READ/WRITE SNAPSHOT */
-
- void RGEN_read_generic(char * s, void * header, size_t h_size)
- {
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- if(fread(header, h_size, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- fclose(fd);
- }
-
- void WGEN_write_generic(char * s, void * header, size_t h_size)
- {
- FILE * fd;
-
- unlink(s);
-
- fd=fopen(s,"w");
- if(fd == NULL)
- WERR_write_error(s, fd);
-
- if(fwrite(header, h_size, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- fclose(fd);
- }
-
- /* SPECIFIC I/O - READ/WRITE .SNA IMAGE */
-
- void RSNA_read_sna(char * s)
- {
- RGEN_read_generic(s, (void *) &sna, sna_size);
- }
-
- void WSNA_write_sna(char * s)
- {
- WGEN_write_generic(s, (void *) &sna, sna_size);
- }
-
- /* SPECIFIC I/O - READ NEW .SP HEADER */
-
- void RVGH_read_vgaspec_header(char * s)
- {
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- if(fread(&vga,vga_size,1,fd)!=1)
- RERR_read_error(s, fd);
-
- fclose(fd);
- }
-
- /* SPECIFIC I/O - READ/WRITE NEW .SP IMAGE */
-
- void RVGA_read_vgaspec(char * s)
- {
- RGEN_read_generic(s, (void *) &vga, vga_size);
- }
-
- void WVGA_write_vgaspec(char * s)
- {
- WGEN_write_generic(s, (void *) &vga, vga_size);
- }
-
- /* SPECIFIC I/O - READ/WRITE OLD .SP IMAGE */
-
- void ROVG_read_old_vgaspec(char * s)
- {
- RGEN_read_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
- }
-
- void WOVG_write_old_vgaspec(char * s)
- {
- WGEN_write_generic(s, (void *)(((char *)&vga)+6), (unsigned int) (vga_size-6));
- }
-
- /* SPECIFIC I/O - READ RAW IMAGE */
-
- void RRAW_read_raw(char * s)
- {
- int i;
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- if(fread(&h, hdr_size, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- /* check if the image was saved the correct way */
- for(i=0;i<9;i++) {
- if(h.in[i]!=expect[i]) {
- fprintf(stderr,"Header of spectum image not ok, ");
- fprintf(stderr,"Spectrum image should be saved with:\n");
- fprintf(stderr,"SAVE *\"b\"CODE 16384,49152");
- fclose(fd);
- exit(EXIT_FILE_ERROR);
- }
- }
-
- if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- fclose(fd);
- }
-
- /* SPECIFIC I/O - READ/WRITE .Z80 IMAGE */
-
- void RZ80_read_z80(char * s)
- {
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- /* read old header part */
- if(fread(&z80,z80_145_size,1,fd)!=1)
- RERR_read_error(s, fd);
-
- /* check for 2.01 format */
- if((z80.pch == (unsigned char) 0) &&
- (z80.pcl == (unsigned char) 0)) {
-
- /* 2.01 or better format, check if we can use this */
- unsigned char *p;
- p = (unsigned char *) &z80;
-
- /* read an aditional 2 bytes */
- if(fread(&p[z80_145_size],2,1,fd)!=1)
- RERR_read_error(s, fd);
-
- if((p[z80_145_size] != (unsigned char) 23) &&
- (p[z80_145_size+1] != (unsigned char) 0)) {
- fprintf(stderr,"%s seems to be a new type Z80 file!\n",s);
- fprintf(stderr,"This program can only read files up to version 2.01 format\n");
- fclose(fd);
- exit(EXIT_FILE_ERROR);
- }
-
- /* we passed this test, read the 23 byte long extra header */
- if(fread(&p[z80_145_size+2],23,1,fd)!=1)
- RERR_read_error(s, fd);
-
- /* we got a complete header now. */
- /* check the type of the file... */
- if((unsigned int) z80.hardware >= 3) {
- fprintf(stderr,"%s is not a 48K Spectrum Z80 file, can't convert!\n",s);
- fclose(fd);
- exit(EXIT_FILE_ERROR);
- }
- /* check if the interface-1 rom was paged in */
- if(z80.if1_paged != (unsigned char) 0) {
- fprintf(stderr,"%s has interface-1 rom paged in, can't convert!\n",s);
- fclose(fd);
- exit(EXIT_FILE_ERROR);
- }
- /* all fine up till now, put PC back to the old place and reset the */
- /* compressed memory bit, the z80_read_page function decompresses. */
- z80.pch = z80.n_pch;
- z80.pcl = z80.n_pcl;
- z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
-
- while(RDPG_z80_read_page(s, fd)!=0);
- } else {
- /* The file is in version 1.45 format. */
- /* Read and decompress if the image is compressed, */
- /* just read if it is not compressed at all... */
-
- if((z80.data & 0x20)!=0) {
- Z80D_z80_decompress(fd,0,(unsigned int) IMSIZE);
- z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
- } else {
- if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
- RERR_read_error(s, fd);
- }
- }
- fclose(fd);
- }
-
- void WZ80_write_z80(char * s)
- {
- FILE * fd;
-
- /* Try to compress the data */
- z80.data=z80.data | Z80C_z80_compress();
-
- unlink(s);
-
- fd=fopen(s,"w");
- if(fd == NULL)
- WERR_write_error(s, fd);
-
- if(fwrite(&z80, z80_145_size, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- if(fwrite(image, (size_t) z80_size, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- fclose(fd);
- }
-
- /* SPECIFIC I/O - READ/WRITE .PRG IMAGE */
-
- void RPRG_read_prg(char * s)
- {
- RGEN_read_generic(s, (void *) &prg, prg_size);
- }
-
- void WPRG_write_prg(char * s)
- {
- WGEN_write_generic(s, (void *) &prg, prg_size);
- }
-
- /* SPECIFIC I/O - READ/WRITE .ACH IMAGE */
-
- void RACH_read_ach(char * s)
- {
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- if(fread(&ach,ach_size,1,fd)!=1)
- RERR_read_error(s, fd);
-
- /* fseek over the 16K ram area */
- if(fseek(fd,16384L,SEEK_CUR)!=0)
- RERR_read_error(s, fd);
-
- if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- fclose(fd);
- }
-
- void WACH_write_ach(char * s)
- {
- char buffer[1024];
- char *p;
- int i;
- struct stat status;
- const char * rom;
- FILE * fd;
- long file_size;
-
- /* clean buffer first */
- p=(char *) buffer;
- for(i=0; i < 1024; i++) p[i]='\0';
-
- unlink(s);
-
- fd=fopen(s,"w");
- if(fd == NULL)
- WERR_write_error(s, fd);
-
- if(fwrite(&ach,ach_size,1,fd)!=1)
- WERR_write_error(s, fd);
-
- strcat(my_directory,"\\spectrum.rom");
-
- rom=NULL;
-
- if(stat("spectrum.rom",&status)>=0) {
- rom="spectrum.rom";
- }
- else if (stat(my_directory,&status)>=0) {
- rom=(const char *) my_directory;
- }
- file_size = status.st_size;
-
- if(rom==NULL) {
- printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
- printf(" format could not be located, Converting anyway. The ROM space\n");
- printf(" will be filled with 0 bytes, the converted file may not work\n");
-
- /* write the 16K ram area as zero's */
- for(i=0; i < 16; i++) {
- if(fwrite(buffer,1024,1,fd)!=1)
- WERR_write_error(s, fd);
- }
- } else {
- if (file_size != 16384) {
- printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .ach\n");
- printf(" format has a wrong size (not 16K). Converting anyway. The ROM space\n");
- printf(" will be filled with 0 bytes, the converted file may not work\n");
-
- /* copy the 16K ROM area */
- for(i=0; i < 16; i++) {
- if(fwrite(buffer,1024,1,fd)!=1)
- WERR_write_error(s, fd);
- }
- } else {
- FILE * fd_specrom;
-
- printf("Using Spectrum ROM: %s\n",rom);
-
- fd_specrom=fopen(rom,"r");
- if(fd_specrom==NULL) {
- perror(rom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
-
- for(i=0; i < 16; i++) {
- if(fread(buffer,1024,1,fd_specrom)!=1) {
- perror(rom);
- fclose(fd_specrom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
- if(fwrite(buffer,1024,1,fd)!=1) {
- perror(s);
- fclose(fd_specrom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
- }
- fclose(fd_specrom);
- }
- }
-
- if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- fclose(fd);
- }
-
- /* SPECIFIC I/O - READ/WRITE .ZX IMAGE */
-
- void RKGB_read_kgb(char * s)
- {
- FILE * fd;
-
- fd=fopen(s,"r");
- if(fd == NULL)
- RERR_read_error(s, fd);
-
- /* fseek over the first 132 bytes */
- if(fseek(fd,132L,SEEK_CUR)!=0)
- RERR_read_error(s, fd);
-
- if(fread(image, (size_t) IMSIZE, 1, fd)!=1)
- RERR_read_error(s, fd);
-
- if(fread(&kgb,kgb_size,1,fd)!=1)
- RERR_read_error(s,fd);
-
- fclose(fd);
- }
-
- void WKGB_write_kgb(char * s)
- {
- char buffer[132];
- char *p;
- int i;
- struct stat status;
- const char * rom;
- FILE * fd;
- long file_size;
-
- /* clean buffer first */
- p=(char *) buffer;
- for(i=0; i < 132; i++) p[i]='\0';
-
- unlink(s);
-
- fd=fopen(s,"w");
- if(fd == NULL)
- WERR_write_error(s, fd);
-
- strcat(my_directory,"\\spectrum.rom");
-
- rom=NULL;
-
- if(stat("spectrum.rom",&status)>=0) {
- rom="spectrum.rom";
- }
- else if (stat(my_directory,&status)>=0) {
- rom=(const char *) my_directory;
- }
- file_size = status.st_size;
-
- if(rom==NULL) {
- printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
- printf(" format could not be located, Converting anyway. The 132 bytes needed\n");
- printf(" from the ROM will be filled with 0 bytes, the converted file may not\n");
- printf(" work\n");
-
- /* write the 132 byte area as zero's */
- if(fwrite(buffer,132,1,fd)!=1)
- WERR_write_error(s, fd);
- } else {
- if (file_size != 16384) {
- printf("Warning: The file \"spectrum.rom\" needed for proper conversion to the .zx\n");
- printf(" format has a wrong size (not 16K). Converting anyway. The 132 bytes\n");
- printf(" needed from the ROM will be filled with 0 bytes, the converted file\n");
- printf(" may not work\n");
-
- /* write the 132 byte area as zero's */
- if(fwrite(buffer,132,1,fd)!=1)
- WERR_write_error(s, fd);
- } else {
- FILE * fd_specrom;
-
- printf("Using Spectrum ROM: %s\n",rom);
-
- fd_specrom=fopen(rom,"r");
-
- if(fd_specrom == NULL) {
- perror(rom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
-
- /* fseek over the first 16384-132 bytes */
- if(fseek(fd_specrom,16252L,SEEK_CUR)!=0) {
- perror(rom);
- fclose(fd_specrom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
- if(fread(buffer,132,1,fd_specrom)!=1) {
- perror(rom);
- fclose(fd_specrom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
- if(fwrite(buffer,132,1,fd)!=1) {
- perror(s);
- fclose(fd_specrom);
- fclose(fd);
- exit(EXIT_WRITE_ERROR);
- }
- fclose(fd_specrom);
- }
- }
-
- if(fwrite(image, (size_t) IMSIZE, 1, fd)!=1)
- WERR_write_error(s, fd);
-
- if(fwrite(&kgb,kgb_size,1,fd)!=1)
- WERR_write_error(s, fd);
-
- fclose(fd);
- }
-
- /* CONVERSION FUNCTIONS - TO .SNA FORMAT */
-
- void VGSN_vgaspec_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
-
- sna.f=vga.f;
- sna.a=vga.a;
- sna.b=vga.b;
- sna.c=vga.c;
- sna.d=vga.d;
- sna.e=vga.e;
- sna.h=vga.h;
- sna.l=vga.l;
-
- sna.fax=vga.fax;
- sna.aax=vga.aax;
- sna.bax=vga.bax;
- sna.cax=vga.cax;
- sna.dax=vga.dax;
- sna.eax=vga.eax;
- sna.hax=vga.hax;
- sna.lax=vga.lax;
-
- sna.ixh=vga.ixh;
- sna.ixl=vga.ixl;
- sna.iyh=vga.iyh;
- sna.iyl=vga.iyl;
-
- sna.border=vga.border;
-
- sna.i=vga.i;
- sna.r=vga.r;
-
- /* If register I has changed, chances are good that it runs in
- IM2 mode */
- if(sna.i==0x3f)
- sna.im=0x01;
- else
- sna.im=0x02;
-
- if((vga.im & 0x01) == 0)
- sna.iff2=0x00;
- else
- sna.iff2=0xff;
-
- sp=256*vga.sph+vga.spl;
- sp=sp-2;
- addr=sp-0x4000;
- image[addr]=vga.pcl;
- image[addr+1]=vga.pch;
-
- sna.sph=sp/256;
- sna.spl=sp%256;
- }
-
- void RASN_raw_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
- unsigned int pc;
-
- pc=0x1bf4; /* entry of "next statement" */
-
- sna.f=0x99;
- sna.a=0x5f;
- sna.b=0x1f;
- sna.c=0xf0;
- sna.d=0x5d;
- sna.e=0x0c;
- sna.h=0x5d;
- sna.l=0x0e;
-
- sna.fax=0x44;
- sna.aax=0x00;
- sna.bax=0x18;
- sna.cax=0x20;
- sna.dax=0x00;
- sna.eax=0x07;
- sna.hax=0x5c;
- sna.lax=0xf1;
-
- sna.ixh=0x03;
- sna.ixl=0xd4;
- sna.iyh=0x5c;
- sna.iyl=0x3a;
-
- sna.i=0x3f;
- sna.r=0x00;
- sna.im=0x01;
- sna.iff2=0xFF;
-
- /* set sp by means of RAMTOP in the image */
- addr=0x5cb2-0x4000;
- sp=256*image[addr+1]+image[addr]-1;
-
- /* Reset ERR NR to no error */
- image[0x5c3a-0x4000]=0xff;
-
- /* Set border by means of BORDCR */
- sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
-
- /* put return address to MAIN-4 (0x1303) on stack */
- sp=sp-2;
- addr=sp-0x4000;
- image[addr]=0x03;
- image[addr+1]=0x13;
-
- sp=sp-2;
- addr=sp-0x4000;
- image[addr]=pc%256;
- image[addr+1]=pc/256;
-
- sna.sph=sp/256;
- sna.spl=sp%256;
- }
-
- void Z8SN_z80_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
-
- sna.f=z80.f;
- sna.a=z80.a;
- sna.b=z80.b;
- sna.c=z80.c;
- sna.d=z80.d;
- sna.e=z80.e;
- sna.h=z80.h;
- sna.l=z80.l;
-
- sna.fax=z80.fax;
- sna.aax=z80.aax;
- sna.bax=z80.bax;
- sna.cax=z80.cax;
- sna.dax=z80.dax;
- sna.eax=z80.eax;
- sna.hax=z80.hax;
- sna.lax=z80.lax;
-
- sna.ixh=z80.ixh;
- sna.ixl=z80.ixl;
- sna.iyh=z80.iyh;
- sna.iyl=z80.iyl;
-
- sna.border=(z80.data/2) & 0x07;
-
- sna.i=z80.i;
-
- if(z80.data==0xff) z80.data=0;
-
- if((z80.data & 0x01)==1)
- sna.r=(z80.r & 0x7f)+0x80;
- else
- sna.r=z80.r & 0x7f;
-
- sna.im=z80.im & 0x03;
-
- if(z80.iff2 != 0)
- sna.iff2=0xff;
- else
- sna.iff2=0x00;
-
- sp=256*z80.sph+z80.spl;
- sp=sp-2;
- addr=sp-0x4000;
-
- sna.sph=sp/256;
- sna.spl=sp%256;
-
- image[addr]=z80.pcl;
- image[addr+1]=z80.pch;
- }
-
- void PRSN_prg_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
-
- sna.b=prg.b;
- sna.c=prg.c;
- sna.d=prg.d;
- sna.e=prg.e;
- sna.h=prg.h;
- sna.l=prg.l;
- sna.fax=prg.fax;
- sna.aax=prg.aax;
- sna.bax=prg.bax;
- sna.cax=prg.cax;
- sna.dax=prg.dax;
- sna.eax=prg.eax;
- sna.hax=prg.hax;
- sna.lax=prg.lax;
-
- sna.ixh=prg.ixh;
- sna.ixl=prg.ixl;
- sna.iyh=prg.iyh;
- sna.iyl=prg.iyl;
-
- /* Set border by means of BORDCR */
- sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
-
- sna.i=prg.i;
-
- if(prg.i==0x3f)
- sna.im=0x01;
- else
- sna.im=0x02;
-
- sp=256*prg.sph+prg.spl;
- sp=sp+4; /* there are two more words on the stack besides PC */
- addr=sp-0x4000;
-
- sna.r=image[addr-3];
- /* the af combo is on the stack */
- sna.f=image[addr-2];
- sna.a=image[addr-1];
-
- sna.sph=sp/256;
- sna.spl=sp%256;
-
- /* interrupts always on ??? */
- sna.iff2=prg.iff2;
- }
-
- void ACSN_ach_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
-
- sna.f=ach.f;
- sna.a=ach.a;
- sna.b=ach.b;
- sna.c=ach.c;
- sna.d=ach.d;
- sna.e=ach.e;
- sna.h=ach.h;
- sna.l=ach.l;
-
- sna.fax=ach.fax;
- sna.aax=ach.aax;
- sna.bax=ach.bax;
- sna.cax=ach.cax;
- sna.dax=ach.dax;
- sna.eax=ach.eax;
- sna.hax=ach.hax;
- sna.lax=ach.lax;
-
- sna.ixh=ach.ixh;
- sna.ixl=ach.ixl;
- sna.iyh=ach.iyh;
- sna.iyl=ach.iyl;
-
- sna.border=ach.border;
-
- sna.i=ach.i;
-
- sna.r=ach.r;
-
- sna.im=ach.im & 0x03;
- if(sna.im == 3)
- sna.im = 0;
-
- sna.iff2=ach.iff2;
-
- sp=256*ach.sph+ach.spl;
- sp=sp-2;
- addr=sp-0x4000;
-
- sna.sph=sp/256;
- sna.spl=sp%256;
-
- image[addr]=ach.pcl;
- image[addr+1]=ach.pch;
- }
-
- void KGSN_kgb_to_sna()
- {
- unsigned int addr;
- unsigned int sp;
-
- sna.f=kgb.f;
- sna.a=kgb.a;
- sna.b=kgb.b;
- sna.c=kgb.c;
- sna.d=kgb.d;
- sna.e=kgb.e;
- sna.h=kgb.h;
- sna.l=kgb.l;
-
- sna.fax=kgb.fax;
- sna.aax=kgb.aax;
- sna.bax=kgb.bax;
- sna.cax=kgb.cax;
- sna.dax=kgb.dax;
- sna.eax=kgb.eax;
- sna.hax=kgb.hax;
- sna.lax=kgb.lax;
-
- sna.ixh=kgb.ixh;
- sna.ixl=kgb.ixl;
- sna.iyh=kgb.iyh;
- sna.iyl=kgb.iyl;
-
- sna.i=kgb.i;
- sna.r=kgb.r;
-
- /* border-colour not found in KGB image */
- /* Set border by means of BORDCR */
- sna.border=(image[0x5c48-0x4000] & 0x38)>>3;
-
- /* determine interrupt mode using the value of register I */
- if (kgb.i_mode_l==0xff)
- sna.im=0x00;
- else if(kgb.i_mode_l==1)
- sna.im=0x02;
- else
- sna.im=0x01;
-
- if((kgb.interruptstatus & 0x01) != 0)
- sna.iff2=0xff;
- else
- sna.iff2=0x0;
-
- sp=256*kgb.sph+kgb.spl;
- sp=sp-2;
- addr=sp-0x4000;
-
- sna.sph=sp/256;
- sna.spl=sp%256;
-
- image[addr]=kgb.pcl;
- image[addr+1]=kgb.pch;
- }
-
- /* CONVERSION FUNCTIONS - FROM .SNA FORMAT */
-
- void SNVG_sna_to_vgaspec()
- {
- unsigned int addr;
- unsigned int sp;
- unsigned int pc;
-
- sp=256*sna.sph+sna.spl;
- addr=sp-0x4000;
- pc=image[addr]+256*image[addr+1];
- sp=sp+2;
-
- vga.S='S';
- vga.P='P';
- vga.len_l=0x00;
- vga.len_h=0xC0;
- vga.start_l=0x00;
- vga.start_h=0x40;
- vga.f=sna.f;
- vga.a=sna.a;
- vga.b=sna.b;
- vga.c=sna.c;
- vga.d=sna.d;
- vga.e=sna.e;
- vga.h=sna.h;
- vga.l=sna.l;
-
- vga.fax=sna.fax;
- vga.aax=sna.aax;
- vga.bax=sna.bax;
- vga.cax=sna.cax;
- vga.dax=sna.dax;
- vga.eax=sna.eax;
- vga.hax=sna.hax;
- vga.lax=sna.lax;
-
- vga.ixh=sna.ixh;
- vga.ixl=sna.ixl;
- vga.iyh=sna.iyh;
- vga.iyl=sna.iyl;
-
- vga.i=sna.i;
- vga.r=sna.r;
-
- vga.im=sna.im & 0x02; /* 0 for IM1, 2 for IM2 */
-
- /* works? how does it know it was IM1 ? */
- if((sna.iff2 & 0x04) != 0)
- vga.im=vga.im | 0x01;
-
- vga.sph=sp/256;
- vga.spl=sp%256;
-
- vga.pch=pc/256;
- vga.pcl=pc%256;
-
- vga.border=sna.border;
-
- vga.res2=0;
- vga.res3=0;
- vga.res4=0;
- vga.res5=0;
- }
-
- void SNZ8_sna_to_z80()
- {
- unsigned int addr;
- unsigned int sp;
- unsigned int pc;
-
- sp=256*sna.sph+sna.spl;
- addr=sp-0x4000;
- pc=image[addr]+256*image[addr+1];
- sp=sp+2;
-
- z80.f=sna.f;
- z80.a=sna.a;
- z80.b=sna.b;
- z80.c=sna.c;
- z80.d=sna.d;
- z80.e=sna.e;
- z80.h=sna.h;
- z80.l=sna.l;
-
- z80.fax=sna.fax;
- z80.aax=sna.aax;
- z80.bax=sna.bax;
- z80.cax=sna.cax;
- z80.dax=sna.dax;
- z80.eax=sna.eax;
- z80.hax=sna.hax;
- z80.lax=sna.lax;
-
- z80.ixh=sna.ixh;
- z80.ixl=sna.ixl;
- z80.iyh=sna.iyh;
- z80.iyl=sna.iyl;
-
- z80.i=sna.i;
- z80.r=sna.r | 0x080; /* bit 7 is stored somewhere else, always set */
- z80.im=sna.im & 0x03;
- z80.im=z80.im + 0x60; /* fixed normal video/kempston joystick */
-
- z80.sph=sp/256;
- z80.spl=sp%256;
-
- z80.pch=pc/256;
- z80.pcl=pc%256;
-
- /* all kinds of stuff put in "data" */
- z80.data=(sna.border & 0x07)*2;
- if((sna.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
-
- /* image is not compressed, compression will be done by the */
- /* z80_write function. */
- z80.data = z80.data & ~0x20; /* reset compressed mode bit to be sure */
-
- if((sna.iff2 & 0x04) != 0) {
- z80.iff1=0xff;
- z80.iff2=0xff;
- } else {
- z80.iff1=0;
- z80.iff2=0;
- }
- }
-
- void SNPR_sna_to_prg(char * n)
- {
- unsigned int addr;
- unsigned int sp;
- int i;
- unsigned char * p;
-
- /* clean header structure first */
- p=(unsigned char *) &prg;
- for(i=0; i < 256; i++)
- p[i]='\0';
-
- prg.c_0x61=0x61; /* size of image in sectors */
- prg.c_0x35=0x35; /* don't know yet */
- prg.c_0x03=0x03; /* don't know yet */
-
- sp=256*sna.sph+sna.spl;
- addr=sp-0x4000;
-
- /* these are on the stack */
- image[addr-1]=sna.a;
- image[addr-2]=sna.f;
- image[addr-3]=sna.r;
- image[addr-4]=sna.iff2;
-
- sp=sp-4;
-
- prg.name[0]='\0';
- strncpy(prg.name,n,10);
- prg.name[10]='\0';
-
- prg.b=sna.b;
- prg.c=sna.c;
- prg.d=sna.d;
- prg.e=sna.e;
- prg.h=sna.h;
- prg.l=sna.l;
-
- prg.fax=sna.fax;
- prg.aax=sna.aax;
- prg.bax=sna.bax;
- prg.cax=sna.cax;
- prg.dax=sna.dax;
- prg.eax=sna.eax;
- prg.hax=sna.hax;
- prg.lax=sna.lax;
-
- prg.ixh=sna.ixh;
- prg.ixl=sna.ixl;
- prg.iyh=sna.iyh;
- prg.iyl=sna.iyl;
-
- prg.i=sna.i;
- prg.iff2=sna.iff2;
-
- prg.sph=sp/256;
- prg.spl=sp%256;
-
- /* prg.border=sna.border; */
- }
-
- void SNAC_sna_to_ach()
- {
- unsigned int addr;
- unsigned int sp;
- unsigned int pc;
- int i;
- unsigned char * p;
-
- /* clean header structure first */
- p=(unsigned char *) &ach;
- for(i=0; i < 256; i++)
- p[i]='\0';
-
- sp=256*sna.sph+sna.spl;
- addr=sp-0x4000;
- pc=image[addr]+256*image[addr+1];
- sp=sp+2;
-
- ach.f=sna.f;
- ach.a=sna.a;
- ach.b=sna.b;
- ach.c=sna.c;
- ach.d=sna.d;
- ach.e=sna.e;
- ach.h=sna.h;
- ach.l=sna.l;
-
- ach.fax=sna.fax;
- ach.aax=sna.aax;
- ach.bax=sna.bax;
- ach.cax=sna.cax;
- ach.dax=sna.dax;
- ach.eax=sna.eax;
- ach.hax=sna.hax;
- ach.lax=sna.lax;
-
- ach.ixh=sna.ixh;
- ach.ixl=sna.ixl;
- ach.iyh=sna.iyh;
- ach.iyl=sna.iyl;
-
- ach.i=sna.i;
- ach.r=sna.r;
-
- ach.border=sna.border;
-
- if((sna.iff2 & 0x04) != 0)
- ach.iff2=0xff;
- else
- ach.iff2=0x00;
-
- ach.im=sna.im;
-
- ach.sph=sp/256;
- ach.spl=sp%256;
-
- ach.pch=pc/256;
- ach.pcl=pc%256;
- }
-
- void SNKG_sna_to_kgb()
- {
- unsigned int addr;
- unsigned int sp;
- unsigned int pc;
- int i;
- unsigned char * p;
-
- /* clean info structure first */
- p = (unsigned char *) &kgb;
- for(i=0; i < 202; i++)
- p[i]='\0';
-
- /* make some assumptions here */
- kgb.is3_1 = 3; /* always 3, don't ask me why */
- kgb.colourmode = 1; /* assume colour */
- kgb.soundmode = 1; /* assume simple sound */
- kgb.haltmode = 1; /* assume not in halt mode */
-
- sp=256*sna.sph+sna.spl;
- addr=sp-0x4000;
- pc=image[addr]+256*image[addr+1];
- sp=sp+2;
-
- kgb.f=sna.f;
- kgb.a=sna.a;
- kgb.b=sna.b;
- kgb.c=sna.c;
- kgb.d=sna.d;
- kgb.e=sna.e;
- kgb.h=sna.h;
- kgb.l=sna.l;
-
- kgb.fax=sna.fax;
- kgb.aax=sna.aax;
- kgb.bax=sna.bax;
- kgb.cax=sna.cax;
- kgb.dax=sna.dax;
- kgb.eax=sna.eax;
- kgb.hax=sna.hax;
- kgb.lax=sna.lax;
-
- kgb.ixh=sna.ixh;
- kgb.ixl=sna.ixl;
- kgb.iyh=sna.iyh;
- kgb.iyl=sna.iyl;
-
- kgb.i=sna.i;
-
- kgb.r=sna.r;
-
- /* kgb.border=sna.border; NOT IN KGB IMAGE! */
-
- /* Interupt mode is stored in a word in the KGB format. */
- /* Use byte accesses to be CPU independent */
-
- switch (sna.im & 0x03) {
- case 0: kgb.i_mode_h = 0xff;
- kgb.i_mode_l = 0xff;
- break;
- case 2: kgb.i_mode_h = 0;
- kgb.i_mode_l = 1;
- break;
- default:kgb.i_mode_h = 0;
- kgb.i_mode_l = 0;
- break;
- }
-
- if((sna.iff2 & 0x04) != 0)
- kgb.interruptstatus=0x01;
- else
- kgb.interruptstatus=0x00;
-
- kgb.sph=sp/256;
- kgb.spl=sp%256;
-
- kgb.pch=pc/256;
- kgb.pcl=pc%256;
- }
-
- /* 16K PAGE READ FUNCTION FOR .Z80 FORMAT */
-
- /*
- * Function returns:
- * 0: No more pages
- * 1: Page read
- */
- int RDPG_z80_read_page(char * s, FILE * fd)
- {
- struct z80_page_s page_info;
- unsigned int len;
- unsigned int pos;
- long f_len;
-
- if(fread(&page_info,z80_pg_size,1,fd)!=1) {
- return 0;
- }
- len = (256 * page_info.blklen_h) + page_info.blklen_l;
-
- switch(page_info.page_num) {
- case 0: fprintf(stderr,"%s - memory page 0 - 48K rom ignored\n",s);
- pos=0x0ffff;
- break;
- case 1: fprintf(stderr,"%s - memory page 1 - Interface 1 rom ignored\n",s);
- pos=0x0ffff;
- break;
- case 2: fprintf(stderr,"%s - memory page 2 - basic samram rom ignored\n",s);
- pos=0x0ffff;
- break;
- case 3: fprintf(stderr,"%s - memory page 3 - monitor samram rom ignored\n",s);
- pos=0x0ffff;
- break;
- case 4: pos=0x04000; /* second 16K of RAM area */
- break;
- case 5: pos=0x08000; /* third 16K of RAM area */
- break;
- case 6: fprintf(stderr,"%s - memory page 6 - shadow rom 8000-BFFF ignored\n",s);
- pos=0x0ffff;
- break;
- case 7: fprintf(stderr,"%s - memory page 7 - shadow rom C000-FFFF ignored\n",s);
- pos=0x0ffff;
- break;
- case 8: pos=0; /* first 16K of RAM area */
- break;
- case 9: fprintf(stderr,"%s - memory page 8 - 128K page 6 ignored\n",s);
- pos=0x0ffff;
- break;
- case 10:fprintf(stderr,"%s - memory page 10 - 128K page7 ignored\n",s);
- pos=0x0ffff;
- break;
- default:fprintf(stderr,"%s - memory page %d - Invalid page number -fatal-\n",s,page_info.page_num);
- exit(EXIT_FILE_ERROR);
- break;
- }
-
- if(pos == (unsigned int) 0x0ffff) {
- /* wrong page, seek over this page */
- if(fseek(fd, (long) len, SEEK_CUR)!=0)
- RERR_read_error(s, fd);
- } else {
- /* Valid 48K page, read and decompress */
-
- f_len = 0 - ftell(fd);
- Z80D_z80_decompress(fd, pos, 16384);
- f_len = f_len + ftell(fd);
-
- if((long) len != f_len) {
- fprintf(stderr,"Z80 image corrupted, can't convert\n");
- fclose(fd);
- exit(EXIT_FILE_ERROR);
- }
- }
- return 1;
- }
-
- /* COMPRESSION/DECOMPRESSION for .Z80 FORMAT */
-
- void Z80D_z80_decompress(FILE * fd, unsigned int start, unsigned int imsize)
- {
- int c,j,k;
- unsigned char l;
- unsigned char im;
-
- j=start;
- while(j<(start+imsize)) {
- c=getc(fd);
- if(c == -1) return;
- im = (unsigned char) c;
-
- if(im!=0xed) {
- image[j++]=im;
- } else {
- c=getc(fd);
- if(c == -1) return;
- im = (unsigned char) c;
- if(im!=0xed) {
- image[j++]=0xed;
- ungetc(im,fd);
- } else {
- /* fetch count */
- k=getc(fd);
- if(k == -1) return;
- /* fetch character */
- c=getc(fd);
- if(c == -1) return;
- l = (unsigned char) c;
- while(k!=0) {
- image[j++]=l;
- k--;
- }
- }
- }
- }
-
- if(j!=(start+imsize)) {
- fprintf(stderr,"Z80 image corrupted, can't decompress\n");
- exit(EXIT_FILE_ERROR);
- }
- }
-
- int Z80C_z80_compress()
- {
- #ifdef __TURBOC__
- unsigned char far * comp;
- #else
- unsigned char * comp;
- #endif
- unsigned int i,j;
- unsigned int num;
- unsigned char c,n;
- unsigned int ed;
-
- z80_size=(unsigned int) IMSIZE;
-
- /*
- * We need an intermediate buffer here, if the compressed image
- * is bigger than the uncompressed image than the image will
- * not be compressed to save space (!)
- */
-
- #ifdef __TURBOC__
- comp=(unsigned char far *) farmalloc((unsigned long)(IMSIZE+0x0100));
- #else
- comp=(unsigned char *) malloc((size_t)(IMSIZE+0x0100));
- #endif
- if(comp==NULL) {
- printf("Warning: Not enough memory to compress the image, using uncopressed image\n");
- return NOTCOMPRESSED;
- }
-
- i=0;
- j=0;
- /* ensure 'ed' is not set */
- ed=NO;
- while(i<IMSIZE) {
- c=image[i];
- i++;
- if(i<IMSIZE) {
- n=image[i];
- } else {
- /* force 'n' to be unequal to 'c' */
- n=c;
- n++;
- }
-
- if(c!=n) {
- comp[j]=c;
- j++;
- if(c==0xed)
- ed=YES;
- else
- ed=NO;
- } else {
- if(c==0xed) {
- /* two times 0xed - special care */
- comp[j]=0xed;
- j++;
- comp[j]=0xed;
- j++;
- comp[j]=0x02;
- j++;
- comp[j]=0xed;
- j++;
- i++; /* skip second ED */
-
- /* because 0xed is valid compressed we don't
- have to watch it! */
- ed=NO;
- } else if(ed==YES) {
- /* can't compress now, skip this double pair */
- comp[j]=c;
- j++;
- ed=NO; /* 'c' can't be 0xed */
- } else {
- num=1;
- while(i<IMSIZE) {
- if(c!=image[i])
- break;
- num++;
- i++;
- if(num==255)
- break;
- }
- if(num <= 4) {
- /* no use to compress */
- while(num!=0) {
- comp[j]=c;
- j++;
- num--;
- }
- } else {
- comp[j]=0xed;
- j++;
- comp[j]=0xed;
- j++;
- comp[j]=(unsigned char) num;
- j++;
- comp[j]=c;
- j++;
- }
- }
- }
-
- if(j >= (IMSIZE-4)) {
- /* compressed image bigger or same than original */
- #ifdef __TURBOC__
- farfree((void far *) comp);
- #else
- free((void *) comp);
- #endif
- return NOTCOMPRESSED;
- }
- }
- /* append "end of compressed area" mark */
- comp[j]=0;
- j++;
- comp[j]=0xed;
- j++;
- comp[j]=0xed;
- j++;
- comp[j]=0;
- j++;
-
- z80_size = j;
-
- /* copy back */
- i=0;
- j=0;
- while(i<IMSIZE)
- image[i++]=comp[j++];
- #ifdef __TURBOC__
- farfree((void far *) comp);
- #else
- free((void *) comp);
- #endif
- return COMPRESSED;
- }
-