void extract_numbers(char*range,int* invalid_character,int ingresso){ char lettera; int pointer=-1; int end_pointer; int start=0; int end=0; int max_entries=get_total_entries(ingresso); while (isdigit(lettera=range[++pointer])) start=start*10+lettera-48; if(!lettera){ /* range is empty or does not contain '-' signs */ if(!pointer)return; /* empty range */ if(start<1)start=1; if(start>65536)start=65536; set_range(start,start,ingresso); /* range is a single number */ return; } /* range contains a '-' sign' */ if(!pointer)start=1; /* '-' is the first char */ end_pointer=pointer+1; while (isdigit(lettera=range[++pointer])) end=end*10+lettera-48; if(lettera){ printf("Too many '-' signs in range %s\n",range); *invalid_character=1; return; } if (pointer==end_pointer) end=max_entries; /* '-' is the last char */ if(start<1)start=1; if(start>65536)start=65536; if(end<1)end=1; if(end>65536)end=65536; if(end<start){ printf("The range %s is invalid\n",range); *invalid_character=1; return; } set_range(start,end,ingresso); }
int get_entry(int count,int ingresso,int* start_address, int* end_address,int* offset,char* entry_name){ unsigned char byte; int power; filetype type; switch (type=detect_type(ingresso)){ case t64: if((count<1)||(count>get_total_entries(ingresso))) return 0; lseek(ingresso,32+32*count,SEEK_SET); read(ingresso,&byte,1); if (byte!=1)return 0; read(ingresso,&byte,1); if (byte==0)return 0; read(ingresso,&byte,1); *start_address=byte; read(ingresso,&byte,1); *start_address=byte*256+*start_address; read(ingresso,&byte,1); *end_address=byte; read(ingresso,&byte,1); *end_address=byte*256+*end_address; read(ingresso,&byte,1); read(ingresso,&byte,1); *offset=0; for(power=0;power<=3;power++){ read(ingresso,&byte,1); *offset=*offset+(byte<<8*power); } read(ingresso,&byte,1); read(ingresso,&byte,1); read(ingresso,&byte,1); read(ingresso,&byte,1); read(ingresso,entry_name,16); entry_name[16]=0; return 1; case p00: *offset=28; lseek(ingresso,8,SEEK_SET); read(ingresso,entry_name,16); entry_name[16]=0; lseek(ingresso,26,SEEK_SET); read(ingresso,&byte,1); *start_address=byte; read(ingresso,&byte,1); *start_address=byte*256+*start_address; *end_address=file_size(ingresso)+*start_address-28; return 1; case prg: *offset=2; strcpy(entry_name," "); lseek(ingresso,0,SEEK_SET); read(ingresso,&byte,1); *start_address=byte; read(ingresso,&byte,1); *start_address=byte*256+*start_address; *end_address=file_size(ingresso)+*start_address-2; return 1; } }
int get_used_entries(FILE *infile) { int total_entries = get_total_entries(infile); int used_entries = 0; int count; struct program_block program; for (count = 1; count <= total_entries; count++) if (get_entry(count, infile, &program) != 0) used_entries++; return used_entries; }
int get_used_entries(int ingresso){ int total_entries=get_total_entries(ingresso); int used_entries=0; int count,used,start_address,end_address,offset; char entry_name[17]; for(count=1;count<=total_entries;count++) if(used=get_entry(count,ingresso,&start_address,&end_address, &offset,entry_name)) used_entries++; return used_entries; }
int get_entry_info(int count, FILE *infile, struct program_block_info *info, unsigned int* offset) { unsigned char byte; int power; if (!ist64(infile)) return 0; if ((count < 1) || (count > get_total_entries(infile))) return 0; if (fseek(infile, 32 + 32 * count, SEEK_SET) != 0) return 0; if (fread(&byte, 1, 1, infile) < 1) return 0; if (byte != 1) return 0; if (fread(&byte, 1, 1, infile) < 1) return 0; if (byte == 0) return 0; if (fread(&byte, 1, 1, infile) < 1) return 0; info->start = byte; if (fread(&byte, 1, 1, infile) < 1) return 0; info->start += byte * 256; if (fread(&byte, 1, 1, infile) < 1) return 0; info->end = byte; if (fread(&byte, 1, 1, infile) < 1) return 0; info->end += byte * 256; if (fseek(infile, 2, SEEK_CUR) != 0) return 0; *offset = 0; for (power = 0; power <= 3; power++) { if (fread(&byte, 1, 1, infile) < 1) return 0; *offset += byte << 8 * power; } if (fseek(infile, 4, SEEK_CUR) != 0) return 0; if (fread(info->name, 16, 1, infile) < 1) return 0; info->name[16] = 0; return 1; }
int get_first_entry(FILE *infile, struct program_block *program) { filetype type = detect_type(infile); int count; int total_entries; int size_of_c64_program; unsigned char byte; if (fseek(infile, 0, SEEK_SET) != 0) return 0; strcpy(program->info.name, " "); switch (type) { case t64: total_entries = get_total_entries(infile); for (count = 1; count <= total_entries; count++) if (get_entry(count, infile, program)) return count; return 0; case p00: if (fseek(infile, 8, SEEK_SET) != 0) return 0; if (fread(program->info.name, 16, 1, infile) < 1) return 0; program->info.name[16] = 0; if (fseek(infile, 26, SEEK_SET) != 0) return 0; /* fall back */ case prg: if (fread(&byte, 1, 1, infile) < 1) return 0; program->info.start = byte; if (fread(&byte, 1, 1, infile) < 1) return 0; program->info.start += byte * 256; size_of_c64_program = file_size(infile) - ftell(infile); program->info.end = size_of_c64_program + program->info.start; if (fread(&program->data, size_of_c64_program, 1, infile) < 1) return 0; return 1; default: return 0; } }
void list_contents(int ingresso){ filetype type; int total_entries,used; int used_entries; char tape_name[25]; int start_address,end_address,count,offset; char entry_name[17]; switch (type=detect_type(ingresso)){ case t64: total_entries=get_total_entries(ingresso); used_entries=get_used_entries(ingresso); get_tape_name(tape_name,ingresso); printf("%d total entr",total_entries); if (total_entries==1) printf("y"); else printf("ies"); printf(", %d used entr",used_entries); if (used_entries==1) printf("y"); else printf("ies"); printf(", tape name: %s\n",tape_name); printf(" Start address End address\n"); printf(" No. Name dec hex dec hex\n"); printf("--------------------------------------------------\n"); for(count=1;count<=total_entries;count++) if(used=get_entry(count,ingresso,&start_address,&end_address, &offset,entry_name)) printf("%5d %s %5d %04x %5d %04x\n",count,entry_name, start_address,start_address,end_address,end_address); return; case p00: get_entry(count,ingresso,&start_address,&end_address, &offset,entry_name); printf("Start address: %d (hex %04x), end address: %d (hex %04x), name: %s\n" ,start_address,start_address,end_address,end_address,entry_name); return; case prg: get_entry(count,ingresso,&start_address,&end_address, &offset,entry_name); printf("Start address: %d (hex %04x), end address: %d (hex %04x)\n" ,start_address,start_address,end_address,end_address); return; } }
int main(int numarg,char** argo){ int opzione=0; int show_help=0; int show_version=0; int list=0; int current_argument; int ingresso; int uscita; char* output_file_name=NULL; char* override_entry_name=NULL; char* temporary_file_name; char* end; int append_WAV=0; int WAV_descriptor; filetype type; int count,used,total,used_entries; int start_address,end_address,offset; char entry_name[17]; struct entry_element* current_file; int first_done=0; int dsp_output=0; int sample_speed; /* Get options */ while ((opzione=getopt(numarg,argo,"hiloe:v"))!=EOF){ switch(opzione){ case 'h': show_help=1; break; case 'i': inverted_waveform=1; break; case 'l': list=1; break; case 'o': output_file_name=(char*)malloc(strlen(optarg)+4); strcpy(output_file_name,optarg); break; case 'e': override_entry=1; override_entry_name=(char*)malloc(strlen(optarg)+4); strcpy(override_entry_name,optarg); break; case 'v': show_version=1; break; default: help(); return 1; }; } if (show_help==1){ help(); return 0; }; if (show_version==1){ version(); return 0; }; if (output_file_name==NULL){ /* -o is not used */ dsp_output=1; output_file_name=(char*)malloc(strlen(SOUNDDEV)+1); strcpy(output_file_name,SOUNDDEV); }; current_argument=optind; if (current_argument==numarg){ printf("No input files specified!\n"); help(); return 1; } if (!list){ if (dsp_output){ if ((uscita=open(SOUNDDEV,O_WRONLY))==-1){ printf("Could not open file %s\n",SOUNDDEV); return 3; } sample_speed = 44100; if (ioctl(uscita, SNDCTL_DSP_SPEED, &sample_speed) != 0 || sample_speed != 44100){ printf("Could not set playback speed to 44100 Hz in file %s\n",SOUNDDEV); return 3; } } else{ if((uscita=open(temporary_file_name=tempnam("/tmp","prg2w"),O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))==-1){ printf("Could not create temporary file in /tmp directory\n"); return 5; }; if (strlen(output_file_name)<5) append_WAV=1; else{ end=output_file_name+strlen(output_file_name)-4; if((strcmp(end,".WAV"))&&(strcmp(end,".wav"))) append_WAV=1; }; if (append_WAV) strcat(output_file_name,".wav"); if((WAV_descriptor=open(output_file_name,O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))==-1){ printf("Could not create file %s\n",output_file_name); unlink(temporary_file_name); return 5; }; } } while (current_argument<numarg){ if ((ingresso=open(argo[current_argument],O_RDONLY))==-1){ printf("Could not open file %s\n",argo[current_argument]); goto fine; }; switch(type=detect_type(ingresso)){ case t64: printf("%s: T64 file\n",argo[current_argument]); break; case p00: printf("%s: P00 file\n",argo[current_argument]); break; case prg: printf("%s: program file\n",argo[current_argument]); break; default: printf("%s is not a recognized file type\n",argo[current_argument]); goto fine; }; if (list){ list_contents(ingresso); goto fine; }; switch(type){ case t64: used_entries=get_used_entries(ingresso); total=get_total_entries(ingresso); empty_list(files_to_convert); files_to_convert=0; if (used_entries==1){ for(count=1;count<=total;count++) if(used=get_entry(count,ingresso,&start_address,&end_address,&offset, entry_name)) set_range(count,count,ingresso); } /* If there is only one used entry, */ /* Only the used one will be */ /* converted */ /* otherwise ask the user */ else get_range_from_keyboard(ingresso); current_file=files_to_convert; while(current_file!=0){ count=current_file->entry; get_entry(count,ingresso,&start_address,&end_address,&offset, entry_name); if (!first_done) first_done=1; else add_silence(uscita); printf("Converting %d (%s)\n",count,entry_name); convert(ingresso,uscita,start_address,end_address,offset,entry_name); current_file=current_file->next; } break; case p00: case prg: if (!first_done) first_done=1; else add_silence(uscita); printf("Converting %s\n",argo[current_argument]); get_entry(count,ingresso,&start_address,&end_address,&offset, entry_name); if(override_entry) { int ix; for(ix = 0; ix < strlen(override_entry_name); ix++) { entry_name[ix] = toupper(override_entry_name[ix]); } } printf("Entry Name: %s (%d)\n",entry_name,strlen(entry_name)); convert(ingresso,uscita,start_address,end_address,offset,entry_name); }; fine: ++current_argument; }; close(uscita); if((!list)&&(!dsp_output)){ if(first_done){ printf("Creating WAV file...\n"); create_WAV(temporary_file_name,WAV_descriptor); } else unlink(output_file_name); } }
static void write_entries_to_window(HWND window, char *filename){ int num_of_entries, entry, row_num = 0; char numstr[6]; filetype type; LVITEMA row; FILE *fd; struct program_block program; HWND preview = GetDlgItem(window, IDC_PREVIEW); HWND text = GetDlgItem(window, IDC_FILE_TYPE); HWND c64name = GetDlgItem(window, IDC_C64_NAME); fd = fopen(filename, "rb"); if (fd == NULL) return; switch (type = detect_type(fd)) { case not_a_valid_file: EnableWindow(preview, FALSE); EnableWindow(c64name, FALSE); SetWindowTextA(text, ""); SetWindowTextA(c64name, ""); fclose(fd); return; case t64: { char message[1000]; char tape_name[25]; int num_of_used_entries; num_of_entries = get_total_entries(fd); num_of_used_entries = get_used_entries(fd); get_tape_name(tape_name, fd); _snprintf(message, 1000, "T64 file with %u total entr%s, %u used entr%s, name %s", num_of_entries, num_of_entries == 1 ? "y" : "ies", num_of_used_entries, num_of_used_entries == 1 ? "y" : "ies", tape_name); SetWindowTextA(text, message); EnableWindow(preview, num_of_used_entries > 1); } EnableWindow(c64name, FALSE); break; case p00: EnableWindow(preview, FALSE); num_of_entries = 1; SetWindowTextA(text, "P00 file"); EnableWindow(c64name, TRUE); break; case prg: EnableWindow(preview, FALSE); num_of_entries = 1; SetWindowTextA(text, "PRG file"); EnableWindow(c64name, TRUE); break; } for (entry = 1; entry <= num_of_entries; entry++) { if (get_entry(entry, fd, &program)) { row.mask = LVIF_TEXT; row.iItem = row_num++; row.iSubItem = 0; row.pszText = numstr; sprintf(numstr, "%u", entry); ListView_InsertItem(preview, &row); row.iSubItem = 1; row.pszText = program.info.name; ListView_SetItem(preview, &row); row.iSubItem = 2; row.pszText = numstr; sprintf(numstr, "%u", program.info.start); ListView_SetItem(preview, &row); row.iSubItem = 3; sprintf(numstr, "%u", program.info.end); ListView_SetItem(preview, &row); } } if (row_num == 1) { ListView_SetItemState(preview, 0, LVIS_SELECTED, LVIS_SELECTED); SetWindowTextA(c64name, program.info.name); } else { SetWindowTextA(c64name, ""); if (IsWindowEnabled(preview)) ListView_SetItemState(preview, 0, LVIS_FOCUSED, LVIS_FOCUSED); } fclose(fd); }
int main(int argc, char** argv){ char *tapename; int currarg,used_entries,total_entries,filesize,offset,diff1,diff2,entries,entry; unsigned char endadd_low, endadd_high; FILE* desc; struct program_block program; for (currarg=1;currarg<argc;currarg++){ if (!lastpart(argv[currarg],".t64")){ tapename=(char*)malloc(strlen(argv[currarg])+5); sprintf(tapename,"%s.t64",argv[currarg]); } else{ tapename=(char*)malloc(strlen(argv[currarg])+1); sprintf(tapename,"%s",argv[currarg]); } printf("%s: ",tapename); desc=fopen(tapename,"rb"); if (desc==NULL){ printf("Cannot open file\n",tapename); goto end2; } if (detect_type(desc)!=t64){ printf("The file is not a T64\n"); goto end; } if ((entries=get_used_entries(desc))!=1){ printf("Sorry, has %d entries, not 1\n",entries); goto end; } total_entries=get_total_entries(desc); for(entry=1;entry<=total_entries;entry++) if (get_entry_info(entry,desc,&program.info,&offset)) break; printf("1 entry, name %s, ",program.info.name); diff1=program.info.end-program.info.start; filesize=file_size(desc); diff2=filesize-offset; if (diff1==diff2){ printf("File OK\n"); goto end; } printf("broken, fixing..."); program.info.end=program.info.start+diff2; endadd_low=program.info.end&255; endadd_high=program.info.end>>8; fclose(desc); desc=fopen(tapename,"r+b"); if (desc==NULL){ printf("failed: %s\n", strerror(errno)); goto end2; } fseek(desc,36+32*entry,SEEK_SET); fwrite(&endadd_low ,1,1,desc); fwrite(&endadd_high,1,1,desc); printf("Fixed\n"); end: fclose(desc); end2: free(tapename); } return 0; }