home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
64'er
/
64ER_CD.iso
/
spec_emu
/
spconv
/
spconv.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-12-13
|
24KB
|
1,346 lines
#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <alloc.h>
void read_image(char * s);
void write_image(char * s);
void read_jpp(char * s);
void write_jpp(char * s);
void read_vgaspec_header(char * s);
void read_vgaspec(char * s);
void write_vgaspec(char * s);
void read_old_vgaspec(char * s);
void write_old_vgaspec(char * s);
void read_raw(char * s);
void read_z80(char * s);
void write_z80(char * s);
void read_prg(char * s);
void write_prg(char * s);
void jpp_to_vgaspec();
void vgaspec_to_jpp();
void raw_to_jpp();
void jpp_to_z80();
void z80_to_jpp();
void jpp_to_prg();
void prg_to_jpp();
void z80_uncompress();
void z80_uncompress();
int z80_compress();
union header_u {
char in[9];
struct {
char type;
unsigned int length;
unsigned int start;
char var;
char res1;
int line;
} header;
} h;
char expect[]={
0x03, /* type CODE */
0x00,0xc0, /* image size */
0x00,0x40, /* image start */
0xff, /* var */
0xff, /* res1 */
0xff,0xff /* line */
};
struct jpp_s {
unsigned char i;
unsigned char lax;
unsigned char hax;
unsigned char eax;
unsigned char dax;
unsigned char cax;
unsigned char bax;
unsigned char fax;
unsigned char aax;
unsigned char l;
unsigned char h;
unsigned char e;
unsigned char d;
unsigned char c;
unsigned char b;
unsigned char iyl;
unsigned char iyh;
unsigned char ixl;
unsigned char ixh;
unsigned char iff2;
unsigned char r;
unsigned char f;
unsigned char a;
unsigned char spl;
unsigned char sph;
unsigned char im;
unsigned char border;
} jpp;
struct vga_s {
/*00*/ unsigned char S;
/*01*/ unsigned char P;
/*02*/ unsigned int len;
/*04*/ unsigned int start;
/*06*/ unsigned char c;
/*07*/ unsigned char b;
/*08*/ unsigned char e;
/*09*/ unsigned char d;
/*0A*/ unsigned char l;
/*0B*/ unsigned char h;
/*0C*/ unsigned char f;
/*0D*/ unsigned char a;
/*0E*/ unsigned char ixl;
/*0F*/ unsigned char ixh;
/*10*/ unsigned char iyl;
/*11*/ unsigned char iyh;
/*12*/ unsigned char cax;
/*13*/ unsigned char bax;
/*14*/ unsigned char eax;
/*15*/ unsigned char dax;
/*16*/ unsigned char lax;
/*17*/ unsigned char hax;
/*18*/ unsigned char fax;
/*19*/ unsigned char aax;
/*1A*/ unsigned char r;
/*1B*/ unsigned char i;
/*1C*/ unsigned char spl;
/*1D*/ unsigned char sph;
/*1E*/ unsigned char pcl;
/*1F*/ unsigned char pch;
/*20*/ unsigned char res2;
/*21*/ unsigned char res3;
/*22*/ unsigned char border;
/*23*/ unsigned char res4;
/*24*/ unsigned char im;
/*25*/ unsigned char res5;
} vga;
struct z80_s {
/*00*/ unsigned char a;
/*01*/ unsigned char f;
/*02*/ unsigned char c;
/*03*/ unsigned char b;
/*04*/ unsigned char l;
/*05*/ unsigned char h;
/*06*/ unsigned char pcl;
/*07*/ unsigned char pch;
/*08*/ unsigned char spl;
/*09*/ unsigned char sph;
/*0A*/ unsigned char i;
/*0B*/ unsigned char r;
/*0C*/ unsigned char data;
/*0D*/ unsigned char e;
/*0E*/ unsigned char d;
/*0F*/ unsigned char cax;
/*10*/ unsigned char bax;
/*11*/ unsigned char eax;
/*12*/ unsigned char dax;
/*13*/ unsigned char lax;
/*14*/ unsigned char hax;
/*15*/ unsigned char aax;
/*16*/ unsigned char fax;
/*17*/ unsigned char iyl;
/*18*/ unsigned char iyh;
/*19*/ unsigned char ixl;
/*1A*/ unsigned char ixh;
/*1B*/ unsigned char iff1;
/*1C*/ unsigned char iff2;
/*1D*/ unsigned char im;
} z80;
struct prg_s {
/*00*/ char name[10];
/*0A*/ char nullbyte;
/*0B*/ unsigned char contains_0x61;
/*0C*/ unsigned char contains_0x35;
/*0D*/ unsigned char contains_0x03;
/*0E*/ unsigned char contains_0x00[0xdc-0x0e];
/*DC*/ unsigned char iyl;
/*DD*/ unsigned char iyh;
/*DE*/ unsigned char ixl;
/*DF*/ unsigned char ixh;
/*E0*/ unsigned char eax;
/*E1*/ unsigned char dax;
/*E2*/ unsigned char cax;
/*E3*/ unsigned char bax;
/*E4*/ unsigned char lax;
/*E5*/ unsigned char hax;
/*E6*/ unsigned char fax;
/*E7*/ unsigned char aax;
/*E8*/ unsigned char e;
/*E9*/ unsigned char d;
/*EA*/ unsigned char c;
/*EB*/ unsigned char b;
/*EC*/ unsigned char l;
/*ED*/ unsigned char h;
/*EE*/ unsigned char iff2;
/*EF*/ unsigned char i;
/*F0*/ unsigned char spl;
/*F1*/ unsigned char sph;
/*F2*/ unsigned char filler[0x0e];
} prg;
#define IMSIZE 49152
unsigned char image[IMSIZE];
unsigned int z80_size;
int intype;
int outtype;
#define RAW 1
#define JPP 2
#define SPECTRUM 3
#define Z80 4
#define PRG 5
#define UNKNOWN 6
unsigned int addr;
unsigned int sp;
unsigned int pc;
int fd;
main(argc,argv)
int argc;
char *argv[];
{
int i;
char *p;
struct stat status;
char * fromstring;
char * tostring;
char * outfile;
if(argc != 3)
{
fprintf(stderr,"SPCONV version 1.02 - %s\n\n",__DATE__);
fprintf(stderr,"Usage: spconv <source> <target>\n\n");
fprintf(stderr,"Source must be a valid .SNA, .SP, .Z80, .PRG or RAW file.\n");
fprintf(stderr,"Target must be a .SNA, .SP, .Z80 or .PRG 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\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 of the same type an error message\n");
fprintf(stderr,"will be generated (unless they are both .SP files)\n");
fprintf(stderr,"\n\nPublic Domain, H. de Groot 1992\n\n");
return 1;
}
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 1;
}
if(stat(argv[1],&status)<0)
{
perror(argv[1]);
return 1;
}
/*
* recognize input type on filename:
*
* .SNA -> JPP file
* .SP -> SPECTRUM file (was VGASPEC)
* .Z80 -> Z80 file
* .PRG -> PRG file
* other -> if exact 48+header -> raw file
* otherwise unknown
*/
intype=UNKNOWN;
p=strrchr(argv[1],'.');
if(p==NULL) p=argv[1]; /* not found, set at begin of string */
if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0))
{
fromstring="from .SNA";
intype=JPP;
}
if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0))
{
fromstring="from .Z80";
intype=Z80;
}
if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0))
{
fromstring="from .SP";
intype=SPECTRUM;
}
if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0))
{
fromstring="from .PRG";
intype=PRG;
}
if(intype==UNKNOWN)
if (status.st_size == (sizeof(h)+IMSIZE))
{
fromstring="from RAW";
intype=RAW;
}
/*
* recognize output type on filename:
*
* .SNA -> JPP file
* .SP -> SPECTRUM file (was VGASPEC)
* .Z80 -> Z80 file
* .PRG -> PRG file
* otherwise unknown
*/
outtype=UNKNOWN;
p=strrchr(argv[2],'.');
if(p==NULL) p=argv[2]; /* not found, set at begin of string */
if((strcmp(p,".SNA")==0) || (strcmp(p,".sna")==0))
{
tostring="to .SNA";
outtype=JPP;
}
if((strcmp(p,".Z80")==0) || (strcmp(p,".z80")==0))
{
tostring="to .Z80";
outtype=Z80;
}
if((strcmp(p,".SP")==0) || (strcmp(p,".sp")==0))
{
tostring="to .SP";
outtype=SPECTRUM;
}
if((strcmp(p,".PRG")==0) || (strcmp(p,".prg")==0))
{
tostring="to .PRG";
outtype=PRG;
}
if(intype==UNKNOWN)
{
fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80 or .PRG file,\r");
fprintf(stderr,"or a Raw file\n");
return 3;
}
if(outtype==UNKNOWN)
{
fprintf(stderr,"Unknown output file format. Must be a .SNA, .SP or .Z80 or .PRG file\n");
return 4;
}
/*
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]));
strcpy(outfile,argv[2]);
}
if(intype==outtype)
{
if(intype!=SPECTRUM)
{
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 3;
}
else
{
if((status.st_size == (sizeof(vga)+IMSIZE)))
{
printf("Converting %s from new .SP format to old .SP format.\n",argv[1]);
read_vgaspec(argv[1]);
write_old_vgaspec(outfile);
return 0;
}
else if((status.st_size == (sizeof(vga)+IMSIZE-6)))
{
read_vgaspec_header(argv[1]);
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 3;
}
printf("Converting %s from old .SP format to new .SP format.\n",argv[1]);
read_old_vgaspec(argv[1]);
vga.S='S';
vga.P='P';
vga.len=0xC000;
vga.start=0x4000;
write_vgaspec(outfile);
return 0;
}
else
{
read_vgaspec_header(argv[1]);
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 3;
}
else
{
fprintf(stderr,"Unknown input file format. Must be a valid .SNA, .SP, .Z80 or .PRG file\n");
return 3;
}
}
}
}
printf("Converting %s %s %s\n",argv[1],fromstring,tostring);
/*
* convert input_file to JPP
*/
if((intype==JPP) && (status.st_size == (sizeof(jpp)+IMSIZE)))
{
read_jpp(argv[1]);
}
else if ((intype==SPECTRUM)&&((status.st_size == (sizeof(vga)+IMSIZE))))
{
read_vgaspec(argv[1]);
vgaspec_to_jpp();
}
else if ((intype==SPECTRUM)&&((status.st_size == (sizeof(vga)+IMSIZE-6))))
{
read_old_vgaspec(argv[1]);
vgaspec_to_jpp();
}
else if (intype==RAW)
{
read_raw(argv[1]);
raw_to_jpp();
}
else if (intype==Z80)
{
read_z80(argv[1]);
z80_to_jpp();
}
else if (intype==PRG)
{
if(status.st_size != (sizeof(prg)+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");
}
read_prg(argv[1]);
prg_to_jpp();
}
else
{
printf("Unrecognized input file type, can't convert\n");
return 3;
}
/*
* convert internal JPP format to output file
*/
if(outtype==JPP)
{
write_jpp(outfile);
}
else if (outtype==SPECTRUM)
{
jpp_to_vgaspec();
write_vgaspec(outfile);
}
else if (outtype==Z80)
{
jpp_to_z80();
write_z80(outfile);
}
else if (outtype==PRG)
{
jpp_to_prg(outfile);
write_prg(outfile);
}
else
{
printf("Unrecognized output file type, can't convert\n");
return 4;
}
return 0;
}
void read_image(char * s)
{
if(read(fd,image,IMSIZE)==-1)
{
perror(s);
exit(1);
}
}
void write_image(char * s)
{
if(write(fd,image,IMSIZE)==-1)
{
perror(s);
exit(2);
}
}
void read_jpp(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&jpp,sizeof(jpp))==-1)
{
perror(s);
exit(1);
}
read_image(s);
close(fd);
}
void write_jpp(char * s)
{
unlink(s);
fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
if(fd<0)
{
perror(s);
exit(2);
}
if(write(fd,&jpp,sizeof(jpp))==-1)
{
perror(s);
exit(2);
}
write_image(s);
close(fd);
}
void read_vgaspec_header(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&vga,sizeof(vga))==-1)
{
perror(s);
exit(1);
}
close(fd);
}
void read_vgaspec(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&vga,sizeof(vga))==-1)
{
perror(s);
exit(1);
}
read_image(s);
close(fd);
}
void write_vgaspec(char * s)
{
unlink(s);
fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
if(fd<0)
{
perror(s);
exit(2);
}
if(write(fd,&vga,sizeof(vga))==-1)
{
perror(s);
exit(2);
}
write_image(s);
close(fd);
}
void read_old_vgaspec(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,((char *)&vga)+6,sizeof(vga)-6)==-1)
{
perror(s);
exit(1);
}
read_image(s);
close(fd);
}
void write_old_vgaspec(char * s)
{
unlink(s);
fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
if(fd<0)
{
perror(s);
exit(2);
}
if(write(fd,((char *)&vga)+6,sizeof(vga)-6)==-1)
{
perror(s);
exit(2);
}
write_image(s);
close(fd);
}
void read_raw(char * s)
{
int i;
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&h,sizeof(h))==-1)
{
perror(s);
exit(1);
}
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");
exit(1);
}
}
read_image(s);
close(fd);
}
void read_z80(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&z80,sizeof(z80))==-1)
{
perror(s);
exit(1);
}
read_image(s);
close(fd);
}
void write_z80(char * s)
{
unlink(s);
fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
if(fd<0)
{
perror(s);
exit(2);
}
if(write(fd,&z80,sizeof(z80))==-1)
{
perror(s);
exit(2);
}
if(write(fd,image,z80_size)==-1)
{
perror(s);
exit(2);
}
close(fd);
}
void jpp_to_vgaspec()
{
sp=256*jpp.sph+jpp.spl;
addr=sp-0x4000;
pc=image[addr]+256*image[addr+1];
sp=sp+2;
vga.S='S';
vga.P='P';
vga.len=0xC000;
vga.start=0x4000;
vga.f=jpp.f;
vga.a=jpp.a;
vga.b=jpp.b;
vga.c=jpp.c;
vga.d=jpp.d;
vga.e=jpp.e;
vga.h=jpp.h;
vga.l=jpp.l;
vga.fax=jpp.fax;
vga.aax=jpp.aax;
vga.bax=jpp.bax;
vga.cax=jpp.cax;
vga.dax=jpp.dax;
vga.eax=jpp.eax;
vga.hax=jpp.hax;
vga.lax=jpp.lax;
vga.ixh=jpp.ixh;
vga.ixl=jpp.ixl;
vga.iyh=jpp.iyh;
vga.iyl=jpp.iyl;
vga.i=jpp.i;
vga.r=jpp.r;
vga.im=jpp.im & 0x02; /* 0 for IM1, 2 for IM2 */
/* works? how does it know it was IM1 ? */
if((jpp.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=jpp.border;
vga.res2=0;
vga.res3=0;
vga.res4=0;
vga.res5=0;
}
void vgaspec_to_jpp()
{
pc=256*vga.pch+vga.pcl;
jpp.f=vga.f;
jpp.a=vga.a;
jpp.b=vga.b;
jpp.c=vga.c;
jpp.d=vga.d;
jpp.e=vga.e;
jpp.h=vga.h;
jpp.l=vga.l;
jpp.fax=vga.fax;
jpp.aax=vga.aax;
jpp.bax=vga.bax;
jpp.cax=vga.cax;
jpp.dax=vga.dax;
jpp.eax=vga.eax;
jpp.hax=vga.hax;
jpp.lax=vga.lax;
jpp.ixh=vga.ixh;
jpp.ixl=vga.ixl;
jpp.iyh=vga.iyh;
jpp.iyl=vga.iyl;
jpp.border=vga.border;
jpp.i=vga.i;
jpp.r=vga.r;
/* If register I has changed, chances are good that it runs in
IM2 mode */
if(jpp.i==0x3f)
jpp.im=0x01;
else
jpp.im=0x02;
if((vga.im & 0x01) == 0)
jpp.iff2=0x00;
else
jpp.iff2=0xff;
sp=256*vga.sph+vga.spl;
sp=sp-2;
addr=sp-0x4000;
image[addr]=vga.pcl;
image[addr+1]=vga.pch;
jpp.sph=sp/256;
jpp.spl=sp%256;
}
void raw_to_jpp()
{
pc=0x1bf4; /* entry of "next statement" */
jpp.f=0x99;
jpp.a=0x5f;
jpp.b=0x1f;
jpp.c=0xf0;
jpp.d=0x5d;
jpp.e=0x0c;
jpp.h=0x5d;
jpp.l=0x0e;
jpp.fax=0x44;
jpp.aax=0x00;
jpp.bax=0x18;
jpp.cax=0x20;
jpp.dax=0x00;
jpp.eax=0x07;
jpp.hax=0x5c;
jpp.lax=0xf1;
jpp.ixh=0x03;
jpp.ixl=0xd4;
jpp.iyh=0x5c;
jpp.iyl=0x3a;
jpp.i=0x3f;
jpp.r=0x00;
jpp.im=0x01;
jpp.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 */
jpp.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;
jpp.sph=sp/256;
jpp.spl=sp%256;
}
void jpp_to_z80()
{
sp=256*jpp.sph+jpp.spl;
addr=sp-0x4000;
pc=image[addr]+256*image[addr+1];
sp=sp+2;
z80.f=jpp.f;
z80.a=jpp.a;
z80.b=jpp.b;
z80.c=jpp.c;
z80.d=jpp.d;
z80.e=jpp.e;
z80.h=jpp.h;
z80.l=jpp.l;
z80.fax=jpp.fax;
z80.aax=jpp.aax;
z80.bax=jpp.bax;
z80.cax=jpp.cax;
z80.dax=jpp.dax;
z80.eax=jpp.eax;
z80.hax=jpp.hax;
z80.lax=jpp.lax;
z80.ixh=jpp.ixh;
z80.ixl=jpp.ixl;
z80.iyh=jpp.iyh;
z80.iyl=jpp.iyl;
z80.i=jpp.i;
z80.r=jpp.r | 0x080; /* bit 7 is stored somewhere else, always set */
z80.im=jpp.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=(jpp.border & 0x07)*2;
if((jpp.r & 0x80)!=0) z80.data=z80.data+1; /* here is bit 7 of r */
z80.data=z80.data | z80_compress();
if((jpp.iff2 & 0x04) != 0)
{
z80.iff1=0xff;
z80.iff2=0xff;
}
else
{
z80.iff1=0;
z80.iff2=0;
}
}
void z80_to_jpp()
{
pc=256*z80.pch+z80.pcl;
jpp.f=z80.f;
jpp.a=z80.a;
jpp.b=z80.b;
jpp.c=z80.c;
jpp.d=z80.d;
jpp.e=z80.e;
jpp.h=z80.h;
jpp.l=z80.l;
jpp.fax=z80.fax;
jpp.aax=z80.aax;
jpp.bax=z80.bax;
jpp.cax=z80.cax;
jpp.dax=z80.dax;
jpp.eax=z80.eax;
jpp.hax=z80.hax;
jpp.lax=z80.lax;
jpp.ixh=z80.ixh;
jpp.ixl=z80.ixl;
jpp.iyh=z80.iyh;
jpp.iyl=z80.iyl;
jpp.border=(z80.data/2) & 0x07;
jpp.i=z80.i;
if(z80.data==0xff) z80.data=0;
if((z80.data & 0x01)==1)
jpp.r=(z80.r & 0x7f)+0x80;
else
jpp.r=z80.r & 0x7f;
jpp.im=z80.im & 0x03;
if(z80.iff2 != 0)
jpp.iff2=0xff;
else
jpp.iff2=0x00;
sp=256*z80.sph+z80.spl;
sp=sp-2;
addr=sp-0x4000;
jpp.sph=sp/256;
jpp.spl=sp%256;
if((z80.data & 0x20)!=0)
z80_uncompress();
/* PC can only be stored in the image after decompression!! */
image[addr]=z80.pcl;
image[addr+1]=z80.pch;
}
void z80_uncompress()
{
unsigned char far * uc;
unsigned int i,j,k;
unsigned char l;
uc=farmalloc(IMSIZE+0x0100);
if(uc==NULL)
{
fprintf(stderr,"Not enough memory to uncompress z80 image\n");
exit(7);
}
j=0;
i=0;
while(i<IMSIZE)
{
if(image[j]!=0xed)
uc[i]=image[j];
else if(image[j+1]!=0xed)
uc[i]=image[j];
else
{
/* fetch count */
k=(int) image[j+2];
/* fetch character */
l=image[j+3];
while(k!=0)
{
uc[i]=l;
i++;
k--;
}
j=j+3;
i--;
}
i++;
j++;
}
if(i!=IMSIZE)
{
fprintf(stderr,"Z80 image corrupted, can't decompress\n");
fprintf(stderr,"i=%u, should be %u\n",i,IMSIZE);
exit(6);
}
/* copy back */
j=0;
i=0;
while(i<IMSIZE)
image[j++]=uc[i++];
farfree(uc);
}
#define NOTCOMPRESSED 0
#define COMPRESSED 0x20
#define NO 0
#define YES 1
int z80_compress()
{
unsigned char far * comp;
unsigned int i,j;
unsigned int num;
unsigned char c,n;
unsigned int ed;
z80_size=IMSIZE;
comp=farmalloc(IMSIZE+0x0100);
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 */
farfree(comp);
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++];
farfree(comp);
return COMPRESSED;
}
void read_prg(char * s)
{
fd=open(s,O_RDONLY|O_BINARY);
if(fd < 0)
{
perror(s);
exit(1);
}
if(read(fd,&prg,sizeof(prg))==-1)
{
perror(s);
exit(1);
}
read_image(s);
close(fd);
}
void write_prg(char * s)
{
unlink(s);
fd=open(s,O_WRONLY|O_CREAT|O_BINARY,0666);
if(fd<0)
{
perror(s);
exit(2);
}
if(write(fd,&prg,sizeof(prg))==-1)
{
perror(s);
exit(2);
}
write_image(s);
close(fd);
}
void prg_to_jpp()
{
jpp.b=prg.b;
jpp.c=prg.c;
jpp.d=prg.d;
jpp.e=prg.e;
jpp.h=prg.h;
jpp.l=prg.l;
jpp.fax=prg.fax;
jpp.aax=prg.aax;
jpp.bax=prg.bax;
jpp.cax=prg.cax;
jpp.dax=prg.dax;
jpp.eax=prg.eax;
jpp.hax=prg.hax;
jpp.lax=prg.lax;
jpp.ixh=prg.ixh;
jpp.ixl=prg.ixl;
jpp.iyh=prg.iyh;
jpp.iyl=prg.iyl;
/* Set border by means of BORDCR */
jpp.border=(image[0x5c48-0x4000] & 0x38)>>3;
jpp.i=prg.i;
if(prg.i==0x3f)
jpp.im=0x01;
else
jpp.im=0x02;
sp=256*prg.sph+prg.spl;
sp=sp+4; /* there are two more words on the stack besides PC */
addr=sp-0x4000;
jpp.r=image[addr-3];
/* the af combo is on the stack */
jpp.f=image[addr-2];
jpp.a=image[addr-1];
jpp.sph=sp/256;
jpp.spl=sp%256;
/* interrupts always on ??? */
jpp.iff2=prg.iff2;
}
void jpp_to_prg(char * n)
{
int i;
unsigned char * p;
/* clean header structure first */
p=(unsigned char *) &prg;
for(i=0; i < 256; i++)
p[i]='\0';
prg.contains_0x61=0x61; /* size of image in sectors */
prg.contains_0x35=0x35; /* don't know yet */
prg.contains_0x03=0x03; /* don't know yet */
sp=256*jpp.sph+jpp.spl;
addr=sp-0x4000;
/* these are on the stack */
image[addr-1]=jpp.a;
image[addr-2]=jpp.f;
image[addr-3]=jpp.r;
image[addr-4]=jpp.iff2;
sp=sp-4;
prg.name[0]='\0';
strncpy(prg.name,n,10);
prg.name[10]='\0';
prg.b=jpp.b;
prg.c=jpp.c;
prg.d=jpp.d;
prg.e=jpp.e;
prg.h=jpp.h;
prg.l=jpp.l;
prg.fax=jpp.fax;
prg.aax=jpp.aax;
prg.bax=jpp.bax;
prg.cax=jpp.cax;
prg.dax=jpp.dax;
prg.eax=jpp.eax;
prg.hax=jpp.hax;
prg.lax=jpp.lax;
prg.ixh=jpp.ixh;
prg.ixl=jpp.ixl;
prg.iyh=jpp.iyh;
prg.iyl=jpp.iyl;
prg.i=jpp.i;
prg.iff2=jpp.iff2;
prg.sph=sp/256;
prg.spl=sp%256;
/* prg.border=jpp.border; */
}