1 /* 2 * Galaksija tape file 3 * 4 * Based on the original "bin2gtp" program by Tomaz Solc 5 * test_namespace()6 * $Id: galaksija.c $ 7 */ 8 9 #include "appmake.h" 10 11 static char *binname = NULL; 12 static char *crtfile = NULL; 13 static char *outfile = NULL; 14 static char *blockname = NULL; 15 static int origin = -1; 16 static char audio = 0; 17 static char fast = 0; 18 static char khz_22 = 0; 19 static char dumb = 0; 20 static char loud = 0; 21 static char help = 0; 22 23 static char bit_state = 0; 24 static uint8_t h_lvl; 25 static uint8_t l_lvl; 26 static uint8_t gal_h_lvl; 27 static uint8_t gal_l_lvl; 28 29 30 31 /* Options that are available for this module */ 32 option_t gal_options[] = { 33 { 'h', "help", "Display this help", OPT_BOOL, &help}, 34 { 'b', "binfile", "Linked binary file", OPT_STR, &binname }, 35 { 'c', "crt0file", "crt0 file used in linking", OPT_STR, &crtfile }, 36 { 'o', "output", "Name of output file", OPT_STR, &outfile }, 37 { 0, "audio", "Create also a WAV file", OPT_BOOL, &audio }, 38 { 0, "fast", "Tweak the audio tones to run a bit faster", OPT_BOOL, &fast }, 39 { 0, "22", "22050hz bitrate option", OPT_BOOL, &khz_22 }, 40 { 0, "dumb", "Just convert to WAV a tape file", OPT_BOOL, &dumb }, 41 { 0, "loud", "Louder audio volume", OPT_BOOL, &loud }, 42 { 0 , "org", "Origin of the binary", OPT_INT, &origin }, 43 { 0 , "blockname", "Name of the code block in tap file", OPT_STR, &blockname}, 44 { 0, NULL, NULL, OPT_NONE, NULL } 45 }; 46 47 48 49 /* two fast cycles for '0', two slow cycles for '1' */ 50 51 void gal_bit(FILE* fpout, unsigned char bit) 52 { 53 int i, period0, period1, pulse_width; 54 55 if (fast) { 56 period1 = 58; 57 period0 = 145; 58 pulse_width = 22; 59 } else { 60 period1 = 75; 61 period0 = 150; 62 pulse_width = 30; 63 } 64 65 if (bit_state) { 66 h_lvl = gal_h_lvl; 67 l_lvl = gal_l_lvl; 68 } else { 69 h_lvl = gal_l_lvl; 70 l_lvl = gal_h_lvl; 71 } 72 73 if (bit) { 74 75 /* '1' */ 76 for (i = 0; i < pulse_width; i++) 77 fputc(l_lvl, fpout); 78 for (i = 0; i < pulse_width; i++) 79 fputc(h_lvl, fpout); 80 81 for (i = 0; i < period1 - 2 * pulse_width; i++) 82 fputc(0x80, fpout); 83 84 for (i = 0; i < pulse_width; i++) 85 fputc(l_lvl, fpout); 86 for (i = 0; i < pulse_width; i++) 87 fputc(h_lvl, fpout); 88 89 for (i = 0; i < period1 - 2 * pulse_width; i++) 90 fputc(0x80, fpout); 91 92 } else { 93 94 /* '0' */ 95 for (i = 0; i < pulse_width; i++) 96 fputc(l_lvl, fpout); 97 for (i = 0; i < pulse_width; i++) 98 fputc(h_lvl, fpout); 99 100 for (i = 0; i < period0 - 2 * pulse_width; i++) 101 fputc(0x80, fpout); 102 } 103 } 104 105 void gal_rawout(FILE* fpout, unsigned char b) 106 { 107 /* bit order is reversed ! */ 108 static unsigned char c[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; 109 int i, interbyte_pause; 110 111 if (fast) 112 interbyte_pause = 200; 113 else 114 interbyte_pause = 225; 115 116 /* interbyte pause */ 117 for (i = 0; i < interbyte_pause; i++) 118 fputc(0x80, fpout); 119 120 /* byte */ 121 for (i = 0; i < 8; i++) 122 gal_bit(fpout, (b & c[i])); 123 } 124 125 #define GTP_BLOCK_STANDARD 0x00 126 #define GTP_BLOCK_TURBO 0x01 127 #define GTP_BLOCK_NAME 0x10 128 129 int gal_exec(char* target) 130 { 131 char filename[FILENAME_MAX + 1]; 132 char wavfile[FILENAME_MAX + 1]; 133 int c, i; 134 int len; 135 136 unsigned long checksum; 137 FILE *fpin, *fpout; 138 139 char basicdef[] = "\001\000A=USR(&2C3A)\015"; 140 int basicdeflen = 15; 141 int datalen; 142 143 if (help) 144 return -1; 145 146 if (binname == NULL || (!dumb && (crtfile == NULL && origin == -1))) { 147 return -1; 148 } 149 150 if (loud) { 151 gal_h_lvl = 0xFF; 152 gal_l_lvl = 0; 153 } else { 154 gal_h_lvl = 0xe0; 155 gal_l_lvl = 0x20; 156 } 157 158 if (dumb) { 159 strcpy(filename, binname); 160 161 } else { 162 163 if (outfile == NULL) { 164 strcpy(filename, binname); 165 suffix_change(filename, ".gtp"); 166 } else { 167 strcpy(filename, outfile); 168 } 169 170 if (blockname == NULL) 171 blockname = zbasename(binname); 172 173 /* Tomaz's code insertion starts here */ 174 175 #if 0 176 /* basic start addr */ 177 h2le_short(0x2c3a+len, &data[0]); 178 /* basic end addr */ 179 h2le_short(0x2c3a+len+basiclen, &data[2]); 180 #endif 181 182 if ((fpin = fopen_bin(binname, crtfile)) == NULL) { 183 exit_log(1,"File open error\n"); 184 } 185 186 if (fseek(fpin, 0, SEEK_END)) { 187 fclose(fpin); 188 exit_log(1,"Couldn't determine size of file\n"); 189 } 190 len = ftell(fpin); 191 fseek(fpin, 0L, SEEK_SET); 192 193 datalen = 4 + len + basicdeflen; 194 195 if ((fpout = fopen(filename, "wb")) == NULL) { 196 exit_log(1,"Can't open output file %s\n", filename); 197 } 198 199 /* **** GTP Header **** */ 200 201 /* *** Name block *** */ 202 203 fputc(GTP_BLOCK_NAME, fpout); /* Block ID: NAME */ 204 writeword(strlen(blockname) + 1, fpout); /* NAME block size */ 205 fputc(0, fpout); 206 fputc(0, fpout); 207 for (i = 0; i <= strlen(blockname); i++) { /* block name string */ 208 fputc(blockname[i], fpout); 209 } 210 211 /* *** Data block *** */ 212 213 fputc(GTP_BLOCK_STANDARD, fpout); /* Block ID: STD SPEED DATA */ 214 writeword(datalen + 6, fpout); /* block size */ 215 fputc(0, fpout); 216 fputc(0, fpout); 217 218 checksum = 0; /* Init checksum */ 219 220 writebyte_cksum(0xa5, fpout, &checksum); 221 writeword_cksum(0x2c36, fpout, &checksum); /* ORG address */ 222 writeword_cksum(0x2c36 + datalen, fpout, &checksum); /* block end location */ 223 writeword_cksum(0x2c36 + 4 + len, fpout, &checksum); /* BASIC start address */ 224 writeword_cksum(0x2c36 + datalen, fpout, &checksum); /* block end location */ 225 226 /* binary file */ 227 228 for (i = 0; i < len; i++) { 229 c = getc(fpin); 230 writebyte_cksum(c, fpout, &checksum); 231 /* fputc(c,fpout);*/ 232 } 233 234 /* basic */ 235 for (i = 0; i < basicdeflen; i++) { /* block name string */ 236 writebyte_cksum(basicdef[i], fpout, &checksum); 237 /*fputc(basicdef[i],fpout);*/ 238 } 239 240 writebyte(255 - (checksum % 256), fpout); /* data checksum */ 241 242 fclose(fpin); 243 fclose(fpout); 244 } 245 246 /* ***************************************** */ 247 /* Now, if requested, create the audio file */ 248 /* ***************************************** */ 249 if ((audio) || (fast) || (loud) || (khz_22)) { 250 if ((fpin = fopen(filename, "rb")) == NULL) { 251 exit_log(1, "Can't open file %s for wave conversion\n", filename); 252 } 253 254 if (fseek(fpin, 0, SEEK_END)) { 255 fclose(fpin); 256 exit_log(1,"Couldn't determine size of file\n"); 257 } 258 len = ftell(fpin); 259 fseek(fpin, 0, SEEK_SET); 260 261 strcpy(wavfile, filename); 262 263 suffix_change(wavfile, ".RAW"); 264 265 if ((fpout = fopen(wavfile, "wb")) == NULL) { 266 exit_log(1,"Can't open output raw audio file %s\n", wavfile); 267 } 268 269 /* leading silence and tone*/ 270 for (i = 0; i < 0x5000; i++) 271 fputc(0x80, fpout); 272 273 /* sync */ 274 gal_rawout(fpout, 0); 275 276 /* program block */ 277 if (len > 0) { 278 for (i = 0; i < len; i++) { 279 c = getc(fpin); 280 gal_rawout(fpout, c); 281 } 282 } 283 284 /* trailing tone and silence (probably not necessary) */ 285 /* 286 gal_bit(fpout,0); 287 gal_tone(fpout); 288 for (i=0; i < 0x10000; i++) 289 fputc(0x80, fpout); 290 */ 291 fclose(fpin); 292 fclose(fpout); 293 294 /* Now complete with the WAV header */ 295 if (khz_22) 296 raw2wav_22k(wavfile,2); 297 else 298 raw2wav(wavfile); 299 300 } /* END of WAV CONVERSION BLOCK */ 301 302 exit(0); 303 } 304