1 /* 2 * PC-8801 application packager 3 * 4 * $Id: pc88.c - Stefano $ 5 */ 6 7 8 #include "appmake.h" 9 #include "fcntl.h" 10 11 /* Binding to functions in nec.c */ 12 extern void nec_rawout (FILE *fpout, unsigned char b); 13 extern void nec_bit (FILE *fpout, unsigned char bit); 14 extern char nec_fast; 15 extern char nec_22; 16 17 static char *binname = NULL; 18 static char *crtfile = NULL; 19 static char *outfile = NULL; 20 static int origin = -1; 21 static char audio = 0; 22 static char dumb = 0; 23 static char help = 0; 24 25 static long elapsed; 26 27 28 /* Options that are available for this module */ 29 option_t pc88_options[] = { 30 { 'h', "help", "Display this help", OPT_BOOL, &help}, 31 { 'b', "binfile", "Linked binary file", OPT_STR, &binname }, newbrain_exec()32 { 'c', "crt0file", "crt0 file used in linking", OPT_STR, &crtfile }, 33 { 'o', "output", "Name of output file", OPT_STR, &outfile }, 34 { 0, "audio", "Create also a WAV file", OPT_BOOL, &audio }, 35 { 0, "fast", "Create a fast loading WAV", OPT_BOOL, &nec_fast }, 36 { 0, "22", "22050hz bitrate option", OPT_BOOL, &nec_22 }, 37 { 0, "dumb", "Just convert to WAV a tape file", OPT_BOOL, &dumb }, 38 { 0 , "org", "Origin of the binary", OPT_INT, &origin }, 39 { 0, NULL, NULL, OPT_NONE, NULL } 40 }; 41 42 43 44 45 void pc88_write_tick(long tick, FILE* fpout) 46 { 47 writelong(elapsed, fpout); 48 writelong(tick, fpout); 49 50 elapsed += tick; 51 } 52 53 54 void pc88_write_data_tag(int datlen, FILE* fpout) 55 { 56 writeword(0x101, fpout); /* Data block TAG ID */ 57 writeword(12 + datlen, fpout); /* Whole TAG len */ 58 /* 1200 baud: actual data number of bytes × 44 59 600 baud: actual data number of bytes × 88 */ 60 pc88_write_tick(44 * datlen, fpout); 61 writeword(datlen, fpout); 62 63 writeword(0x01cc, fpout); /* 00CCH (600baud) or 01CCH (1200baud). */ 64 } 65 66 67 68 long getlong (FILE *fpin) 69 { 70 return (fgetc(fpin)+256*fgetc(fpin)+65536*fgetc(fpin)+16777216*fgetc(fpin)); 71 } 72 73 74 /* 75 * Execution starts here 76 */ 77 78 int pc88_exec(char* target) 79 { 80 char filename[FILENAME_MAX + 1]; 81 char wavfile[FILENAME_MAX+1]; 82 char name[10]; 83 char buf[25]; 84 FILE* fpin; 85 FILE* fpout; 86 int len, len2; 87 long pos; 88 unsigned long checksum, ticks; 89 int i, j; 90 91 if (help) 92 return -1; 93 94 if (binname == NULL || (!dumb && (crtfile == NULL && origin == -1))) { 95 return -1; 96 } 97 98 99 /* Creating the ".T88" file */ 100 101 if (dumb) 102 strcpy(filename, binname); 103 104 else { 105 106 if (outfile == NULL) { 107 strcpy(filename, binname); 108 suffix_change(filename, ".t88"); 109 } else { 110 strcpy(filename, outfile); 111 } 112 113 if (strcmp(binname, filename) == 0) { 114 exit_log(1,"Input and output file names must be different\n"); 115 } 116 117 if (origin != -1) { 118 pos = origin; 119 } else { 120 if ((pos = get_org_addr(crtfile)) == -1) { 121 exit_log(1,"Could not find parameter ZORG (not z88dk compiled?)\n"); 122 } 123 } 124 125 if ((fpin = fopen_bin(binname, crtfile)) == NULL) { 126 exit_log(1, "Can't open input file %s\n", binname); 127 } 128 129 if (fseek(fpin, 0, SEEK_END)) { 130 fclose(fpin); 131 exit_log(1, "Couldn't determine size of file\n"); 132 } 133 134 len = ftell(fpin); 135 136 fseek(fpin, 0L, SEEK_SET); 137 138 if ((fpout = fopen(filename, "wb")) == NULL) { 139 fclose(fpin); 140 exit_log(1,"Can't open output file\n"); 141 } 142 143 144 elapsed=0; 145 146 /* T88 FILE HEADER */ 147 writestring("PC-8801 Tape Image(T88)", fpout); 148 writebyte(0, fpout); /* String termination */ 149 150 /* Version TAG */ 151 writeword(1, fpout); /* TAG ID for version */ 152 writeword(2, fpout); /* TAG len */ 153 writeword(0x100, fpout); /* V.0100 */ 154 155 /* Blank space */ 156 //writeword(0x100, fpout); /* TAG ID for blank */ 157 //writeword(8, fpout); /* TAG len */ 158 //pc88_write_tick(10000, fpout); 159 160 /* LEADER */ 161 writeword(0x102, fpout); /* TAG ID for space */ 162 writeword(8, fpout); /* TAG len */ 163 pc88_write_tick(7928, fpout); 164 165 /* Filename block leading tone */ 166 writeword(0x103, fpout); /* TAG ID for mark */ 167 writeword(8, fpout); /* TAG len */ 168 pc88_write_tick(1320, fpout); 169 170 /* Deal with the filename */ 171 strcpy(name, "$$$ "); 172 for (i = 0; (i < 6) && (isalnum(filename[i])); i++) 173 name[i+3] = toupper(filename[i]); 174 175 pc88_write_data_tag(9, fpout); 176 for (i = 0; i < 9; i++) 177 writebyte(name[i], fpout); 178 179 /* Data block leading tone */ 180 writeword(0x103, fpout); /* TAG ID for mark */ 181 writeword(8, fpout); /* TAG len */ 182 pc88_write_tick(330, fpout); 183 184 185 /* Binary block */ 186 pc88_write_data_tag(len + 7 + 3 * ((len+127)/128), fpout); /* Total length */ 187 188 /* Data block with ORG position */ 189 checksum = 0; 190 writebyte(0x3a, fpout); 191 writebyte_cksum((unsigned char)(pos >> 8), fpout, &checksum); // MSB 192 writebyte_cksum((unsigned char)(pos & 0xff), fpout, &checksum); // LSB 193 writebyte(0x100 - (checksum & 0xff), fpout); 194 195 len2=128; 196 for (i=0; i<len; i+=len2) { 197 if ((len-i)<128) len2=len-i; 198 writebyte(0x3a, fpout); 199 checksum = 0; 200 writebyte_cksum(len2, fpout, &checksum); 201 for (j = 0; j < len2; j++) { 202 writebyte_cksum(getc(fpin),fpout, &checksum); 203 } 204 writebyte(0x100 - (checksum & 0xff), fpout); 205 } 206 207 writebyte(0x3a, fpout); 208 writebyte(0x00, fpout); 209 writebyte(0x3a, fpout); // end 210 211 /* Tail */ 212 writeword(0x103, fpout); /* TAG ID for mark */ 213 writeword(8, fpout); /* TAG len */ 214 pc88_write_tick(3966, fpout); 215 216 writeword(0x102, fpout); /* TAG ID for space */ 217 writeword(8, fpout); /* TAG len */ 218 pc88_write_tick(9252, fpout); 219 220 /* End TAG */ 221 writeword(0, fpout); /* TAG ID for END */ 222 writeword(0, fpout); /* TAG body (no content) */ 223 224 225 fclose(fpin); 226 fclose(fpout); 227 } 228 229 /* ***************************************** */ 230 /* Now, if requested, create the audio file */ 231 /* ***************************************** */ 232 if ((audio) || (nec_fast) || (nec_22)) { 233 if ( (fpin=fopen(filename,"rb") ) == NULL ) { 234 exit_log(1,"Can't open file %s for wave conversion\n",filename); 235 } 236 237 for (i=0; i<23; i++) 238 buf[i]=fgetc(fpin); 239 if (strncmp(buf,"PC-8801 Tape Image(T88)",23)) { 240 fclose(fpin); 241 exit_log(1,"The file to be converted is not in T88 format.\n"); 242 } 243 fgetc(fpin); 244 245 strcpy(wavfile,filename); 246 247 suffix_change(wavfile,".RAW"); 248 249 if ( (fpout=fopen(wavfile,"wb") ) == NULL ) { 250 exit_log(1,"Can't open output raw audio file %s\n",wavfile); 251 } 252 253 while (i!=0) { 254 i=fgetc(fpin)+256*fgetc(fpin); 255 switch (i) 256 { 257 case 1: 258 fgetc(fpin); fgetc(fpin); 259 if (dumb) { 260 printf ("T88 file version: "); 261 printf ("%X\n",fgetc(fpin)+256*fgetc(fpin)); 262 } else { 263 fgetc(fpin); fgetc(fpin); 264 } 265 break; 266 case 0x100: 267 if (dumb) 268 printf (" -Blank- : "); 269 fgetc(fpin); fgetc(fpin); /* TAG length */ 270 ticks=getlong(fpin); 271 if (dumb) 272 printf (" elapsed=%0.2f sec., ",(float) ticks / 4800); 273 ticks=getlong(fpin); 274 if (dumb) 275 printf (" ticks=%0.2f sec.\n",(float) ticks / 4800); 276 277 for (i = 0; (i < ticks); i++) /* duration approximated */ 278 fputc(0x80, fpout); 279 280 break; 281 case 0x102: 282 if (dumb) 283 printf (" SPACE tone : "); /* 1200 */ 284 fgetc(fpin); fgetc(fpin); /* TAG length */ 285 ticks=getlong(fpin); 286 if (dumb) 287 printf (" elapsed=%0.2f sec., ",(float) ticks / 4800); 288 ticks=getlong(fpin); 289 if (dumb) 290 printf (" ticks=%0.2f sec.\n",(float) ticks / 4800); 291 292 for (i = 0; (i < (ticks/4)); i++) /* duration approximated */ 293 nec_bit(fpout, 0); 294 295 break; 296 case 0x103: 297 if (dumb) 298 printf (" MARK tone : "); /* 2400 */ 299 fgetc(fpin); fgetc(fpin); /* TAG length */ 300 ticks=getlong(fpin); 301 if (dumb) 302 printf (" elapsed=%0.2f sec., ",(float) ticks / 4800); 303 ticks=getlong(fpin); 304 if (dumb) 305 printf (" ticks=%0.2f sec.\n",(float) ticks / 4800); 306 307 for (i = 0; (i < (ticks/4)); i++) /* duration approximated */ 308 nec_bit(fpout, 1); 309 310 break; 311 case 0x101: 312 if (dumb) 313 printf (" Data block : "); 314 i=fgetc(fpin)+256*fgetc(fpin); 315 if (dumb) 316 printf ("TAG length: %d\n",i); 317 for (j=1; j<=10; j++) fgetc(fpin); 318 j=fgetc(fpin)+256*fgetc(fpin); 319 switch (j) { 320 case 0x00cc: 321 printf (" 600 baud. WARNING: data will be saved at 1200 bps\n"); 322 break; 323 case 0x01cc: 324 if (dumb) 325 printf (" 1200 baud\n"); 326 break; 327 default: 328 printf (" WARNING: unexpected value for 'baud rate': 0x%X\n",j); 329 break; 330 } 331 i-=12; 332 for (j=1; j<=i; j++) 333 nec_rawout(fpout,fgetc(fpin)); 334 break; 335 default: 336 if (dumb) 337 printf ("TAG type: %X\n",i); 338 i=fgetc(fpin)+256*fgetc(fpin); 339 if (dumb) 340 printf ("TAG len: %X\n",i); 341 for (j=1; j<=i; j++) fgetc(fpin); 342 break; 343 } 344 } 345 fclose(fpin); 346 fclose(fpout); 347 348 /* Now complete with the WAV header */ 349 if (nec_22) 350 raw2wav_22k(wavfile,2); 351 else 352 raw2wav(wavfile); 353 } 354 355 return 0; 356 } 357