/* ----------------------
* P C V D U M P V 1.00
* ----------------------
* Displays .PCV (PCVIC system snapshot) files & checks them for validity.
* Versions supported: 1.0
*
* Copyright (C) 16 jan 1998 by B.W. van Schooten.
*
* This program is freely useable, and freely modifiable as long as it is
* made clear that the original program has been modified.
*/
#define USAGE \
"\n"\
"Usage: PCVDUMP sourcefile targetfile\n"\
"\n"\
"The source file must be a PCV (Vic-20) system snapshot.\n"\
"Header information will be printed to stdout. The contents of the memory\n"\
"space will be decompressed and written to the targetfile. Diagnostic\n"\
"messages are written to stderr.\n"\
"\n"
#include
#include
#define ERROR_NONE 0
#define ERROR_EOF 1
#define ERROR_TOOLONG 2
char *decompressmsg[] = {
"Done.\n",
"\nERROR: EOF found when data was expected.\n",
"\nERROR: Data runs past expected end address.\n"
};
int
decompress (long, FILE *, FILE *);
/* Usage: error=decompress(size, inputfile, outputfile)
* Decompresses Byterun-compressed data from inputfile, writing the result
* to outputfile.
*
* Byterun is a simple compression method, based on replacing a row of
* bytes which have the same value by a count and a value byte. It is used
* for example in ILBM images.
*
* This routine also updates the checksum as the data is read.
*/
void
interpretrsb100 (FILE *,int);
/* Shows information of register state block (rsb) as it is found in
* version 1.00. File pointer should point to start of rsb.
* File pointer is left undefined.
*/
void
addtochecksum (unsigned char);
/* Calculates new checksum according to given byte. Checksum is stored in
* GLOBAL variable checksum.
*/
void
closedown (int);
/* Closes any open files and exits with supplied exit code
*/
const char *headerstr="PCVIC system snapshot";
#define HEADERSTRLEN 22
/* length includes zero terminator */
long checksum;
FILE *inp, *outp;
void
main(int argc,char **argv) {
int n,m; /* loop counters */
unsigned char c1,c2; /* temp. input characters */
int rsbsize; /* size field of register state block */
long rsbstart; /* file pointer to start of reg.state block */
int decompresserror; /* error returned by decompress procedure */
unsigned int checksumread; /* value of checksum as read from file */
int version; /* PCV version, ex. 100=1.00, 110=1.10 */
inp=NULL;
outp=NULL;
checksum=0x7ffb;
fprintf(stderr,"PCVDUMP 1.00, (C) 16 jan 1998 by B.W. van Schooten\n");
if (argc!=3) {
fprintf(stderr,USAGE);
closedown(EXIT_SUCCESS);
}
/*
* OPEN FILES
*/
inp=fopen(argv[1],"rb");
if (!inp) {
fprintf(stderr,"ERROR: Cannot open file %s.\n",argv[1]);
closedown(EXIT_FAILURE);
}
outp=fopen(argv[2],"wb");
if (!outp) {
fprintf(stderr,"ERROR: Cannot write file %s.\n",argv[2]);
closedown(EXIT_FAILURE);
}
/*
* MATCH HEADER
*/
n=0;
while (1) {
c1=(unsigned char)fgetc(inp);
if (feof(inp)) {
fprintf(stderr,"ERROR: EOF in header.\n");
closedown(EXIT_FAILURE);
}
if (c1!=headerstr[n]) break;
n++;
if (n==HEADERSTRLEN) break;
}
if (n!=HEADERSTRLEN) {
fprintf(stderr,"ERROR: Header does not match.\n");
closedown(EXIT_FAILURE);
}
/*
* GET VERSION NUMBER
*/
c1=(unsigned char)fgetc(inp);
addtochecksum(c1);
c2=(unsigned char)fgetc(inp);
addtochecksum(c2);
if (feof(inp)) {
fprintf(stderr,"ERROR: EOF in version number.\n");
closedown(EXIT_FAILURE);
}
if (c1>=100) {
fprintf(stderr,"ERROR: minor version out of valid range.\n");
closedown(EXIT_FAILURE);
}
version=c1+100*c2;
printf("SnapshotVersion=%d.%02d\n",(int)c2,(int)c1);
/*
* GET SIZE OF REGISTER STATE BLOCK
*/
c1=(unsigned char)fgetc(inp);
addtochecksum(c1);
c2=(unsigned char)fgetc(inp);
addtochecksum(c2);
if (feof(inp)) {
fprintf(stderr,"ERROR: EOF in register state block size.\n");
closedown(EXIT_FAILURE);
}
rsbsize=(int)c1 + 256*(int)c2;
printf("RSBSize=%u\n",rsbsize);
if (rsbsize>32767) {
fprintf(stderr,"ERROR: Register state block size more than 32767.\n");
closedown(EXIT_FAILURE);
}
rsbstart = ftell(inp);
/*
* CHECKSUM OVER REGISTER STATE BLOCK
*/
for (n=0; n128) { /* 129..255: duplicate byte n times */
databyte=(unsigned char)fgetc(inp);
addtochecksum(databyte);
if (feof(inp)) return (ERROR_EOF);
for (n=0; n<257-leaderbyte; n++) {
fputc(databyte, outp);
runningtotal++;
}
}
/* 128: ignore byte */
if (runningtotal==bytes) return(ERROR_NONE);
if (runningtotal>bytes) return(ERROR_TOOLONG);
}
}
void
interpretrsb100(FILE *inp, int rsbsize) {
unsigned char c1,c2;
unsigned int value;
if (rsbsize!=35) {
fprintf(stderr,"WARNING: Register state block size should be 35.\n");
}
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
value=c1+256*c2;
printf("X=$%04X\n",value);
if (c2!=0) fprintf(stderr,"WARNING: Hi byte must be 0.\n");
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
value=c1+256*c2;
printf("Y=$%04X\n",value);
if (c2!=0) fprintf(stderr,"WARNING: Hi byte must be 0.\n");
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
value=c1+256*c2;
printf("S=$%04X\n",value);
if (c2!=1) fprintf(stderr,"WARNING: Hi byte must be 1.\n");
c1=(unsigned char)fgetc(inp);
printf("OLDSCANCOUNT=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("AUXFLAGS=%02X\n",c1);
if (c1 & 0xc3) fprintf(stderr,"WARNING: Bit 0,1,6,7 should all be 0.\n");
if (!(c1 & 0x20)) fprintf(stderr,"WARNING: Bit 5 should always be 1.\n");
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
value=c1+256*c2;
printf("SCANLINE=$%02X\n",value);
if (value>32767)
fprintf(stderr,"WARNING: Value should not exceed 32767.\n");
c1=(unsigned char)fgetc(inp);
printf("IFR1=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("IER1=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("IFR2=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("IER2=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("PERIP1B=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("LATCH1B=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("PERIP1A=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("LATCH1A=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("PERIP2B=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("LATCH2B=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("PERIP2A=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("LATCH2A=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("TIMERSTATUS=$%02X\n",c1);
if (c1 & 0xf0) fprintf(stderr,"WARNING: high four bits should be zero.\n");
c1=(unsigned char)fgetc(inp);
printf("V1T2LATCHL=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("V2T2LATCHL=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("V1T2TIMERL=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("V2T2TIMERL=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("NMIFLANK=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("MEMCONFIG=$%02X\n",c1);
if (c1 & 0xd0)
fprintf(stderr,"WARNING: Bit 7,6 and 3 should all be zero.\n");
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
value=c1+256*c2;
printf("PC=$%04X\n",value);
c1=(unsigned char)fgetc(inp);
c2=(unsigned char)fgetc(inp);
printf("MAINFLAGS=$%02X(H) $%02X(L)\n",c2,c1);
if (c2 & 0xbe)
fprintf(stderr,
"WARNING: Bit 7,5,4,3,2,1 of high byte should be zero.\n");
c1=(unsigned char)fgetc(inp);
printf("A=$%02X\n",c1);
c1=(unsigned char)fgetc(inp);
printf("SCANCOUNT=$%02X\n",c1);
}
void
addtochecksum(unsigned char nextbyte) {
long tmp1,tmp2, carryout;
tmp1=checksum;
tmp2=(long)nextbyte;
/*
* ROL W[checksum],1
*/
tmp1 <<= 1;
carryout = (tmp1 & 0x10000);
if (carryout) tmp1 |= 1;
tmp1 &= 0xffff;
/*
* CBW
*/
if (tmp2 >= 128) tmp2 |= 0xff00;
/*
* ADD [checksum],AX
*/
tmp1 += tmp2;
tmp1 &= 0xffff;
checksum=tmp1;
/* printf("C%x ",(int) checksum);*/
}
void
closedown(int exitcode) {
if (inp) fclose(inp);
if (outp) fclose(outp);
exit(exitcode);
}
               (
geocities.com/timessquare/alley)                   (
geocities.com/timessquare)