138 lines
2.7 KiB
Text
138 lines
2.7 KiB
Text
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <stdio.h>
|
|
|
|
typedef unsigned char u_char;
|
|
typedef unsigned short u_short;
|
|
|
|
typedef struct direntry {
|
|
unsigned char une[12];
|
|
#define d_user une[0]
|
|
#define d_name une[1]
|
|
#define d_ext une[9]
|
|
u_short d_fext;
|
|
u_char d_fill;
|
|
u_char d_last;
|
|
u_short d_blks[8];
|
|
} DIR;
|
|
|
|
#define UNUSED 0xE5
|
|
|
|
#define DIROFFSET 0x2000
|
|
#define DIRBLKS 16
|
|
#define BLKSTART (DIROFFSET+DIRBLKS*128)
|
|
#define CLSTSIZE 2048
|
|
|
|
typedef struct fileentry {
|
|
char f_name[30];
|
|
u_short f_fext;
|
|
u_char f_last;
|
|
u_short f_blks[200];
|
|
} FENTRY;
|
|
|
|
void makename(char* name, DIR* dir)
|
|
{
|
|
int i;
|
|
char *p = name;
|
|
for (i=0; i<8; i++) {
|
|
if ((&dir->d_name)[i]==' ') break;
|
|
*p++ = (&dir->d_name)[i];
|
|
}
|
|
*p++ = '.';
|
|
for (i=0; i<3; i++) {
|
|
if ((&dir->d_ext)[i]==' ') break;
|
|
*p++ = (&dir->d_ext)[i];
|
|
}
|
|
*p = 0;
|
|
}
|
|
|
|
FENTRY* lookup(char* name, FENTRY* files)
|
|
{
|
|
FENTRY* nul=0, *p = files;
|
|
int i;
|
|
|
|
for (i = 0; i<64; i++) {
|
|
if (p->f_name[0]==0) {
|
|
if (nul==0) nul = p;
|
|
} else {
|
|
if (!strcmp(p->f_name,name)) {
|
|
return p;
|
|
}
|
|
}
|
|
p++;
|
|
}
|
|
if (nul==0) {
|
|
printf("File table full!\n");
|
|
exit(1);
|
|
}
|
|
return nul;
|
|
}
|
|
|
|
int main(int argc,char* argv[])
|
|
{
|
|
FILE *in,*out;
|
|
unsigned char cpmbuf[2048];
|
|
int i,k,n,s,ls;
|
|
char name[30];
|
|
FENTRY files[64], *fe;
|
|
DIR* dir;
|
|
|
|
if (argc != 2) {
|
|
fprintf(stderr,"Usage: %s cpmdisk.bin\n",argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
for (i=0; i<64; i++) {
|
|
files[i].f_name[0] = 0;
|
|
files[i].f_fext = 0;
|
|
files[i].f_last = 0;
|
|
memset(files[i].f_blks,0,sizeof(u_short)*200);
|
|
}
|
|
|
|
in = fopen(argv[1],"rb");
|
|
if (!in) {
|
|
perror("open file");
|
|
exit(1);
|
|
}
|
|
fseek(in,DIROFFSET,0);
|
|
for (i=0; i<DIRBLKS; i++) {
|
|
fread(cpmbuf,sizeof(DIR),4,in);
|
|
for (k=0; k<4; k++) {
|
|
dir = (DIR*)(cpmbuf+k*sizeof(DIR));
|
|
if (dir->d_user == UNUSED) continue;
|
|
makename(name,dir);
|
|
fe = lookup(name,files);
|
|
strcpy(fe->f_name,name);
|
|
if (dir->d_fext >= fe->f_fext) {
|
|
fe->f_fext = dir->d_fext;
|
|
fe->f_last = dir->d_last;
|
|
}
|
|
for (n=0; n<8; n++) {
|
|
fe->f_blks[dir->d_fext*8+n] = dir->d_blks[n];
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i=0; i<64; i++) {
|
|
if (!files[i].f_name[0]) continue;
|
|
printf("File %s: (last=%d)\n",files[i].f_name,files[i].f_last%16);
|
|
FILE* out = fopen(files[i].f_name,"wb");
|
|
|
|
|
|
|
|
for (k=0; k<199; k++) {
|
|
n = files[i].f_blks[k];
|
|
if (n==0) break;
|
|
fseek(in,BLKSTART+CLSTSIZE*(n-1),0);
|
|
fread(cpmbuf,1,2048,in);
|
|
ls = files[i].f_last % 16;
|
|
if (!ls) ls = 16;
|
|
s = files[i].f_blks[k+1]==0 ? ls*128 : CLSTSIZE;
|
|
fwrite(cpmbuf,1,s,out);
|
|
printf("%d ",files[i].f_blks[k]);
|
|
}
|
|
printf("\n");
|
|
fclose(out);
|
|
}
|
|
exit(0);
|
|
}
|