tool to upload data to a SuperCharger cartridge
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

makewav.c 36KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296
  1. /*
  2. Written by Bob Colbert
  3. released to the public domain
  4. The author assumes no responsibility for any damage caused by the use or
  5. posession of this program. USE AT YOUR OWN RISK!!!
  6. Small changes by SvOlli
  7. */
  8. #include <stdio.h>
  9. #include <string.h>
  10. #include <strings.h>
  11. #include <math.h>
  12. #include <stdlib.h>
  13. #include <unistd.h>
  14. #include "queue.h"
  15. #include "makewav.h"
  16. #include "paplay.h"
  17. #include "streambuffer.h"
  18. #include "version.h"
  19. #define WAV_MODE 0
  20. #define RAW_MODE 1
  21. #define AUD_MODE 2
  22. #define CREATE_IN_RAM 1
  23. FILE *binFile,
  24. *wavFile;
  25. unsigned char buffer[260],
  26. fileBuffer[0x10000],
  27. pageList[24],
  28. emptyPage[256];
  29. float flength,
  30. wavFlength;
  31. void freadall( void *b, size_t size, FILE *f )
  32. {
  33. char *c = (char*)b;
  34. size_t pos = 0;
  35. size_t dread = 0;
  36. for( pos = 0; pos < size; pos += size )
  37. {
  38. dread = fread( c + pos, 1, size - pos, f );
  39. if( dread == 0 )
  40. {
  41. break;
  42. }
  43. }
  44. if( pos != size )
  45. {
  46. fprintf( stderr, "short read: could only get %u bytes out of %u\n",
  47. (unsigned int)pos, (unsigned int)size );
  48. exit( 2 );
  49. }
  50. }
  51. void processByte( streambuffer_t *buffer, unsigned char pByte, int mode )
  52. {
  53. int p;
  54. if( (mode == WAV_MODE) || (mode == AUD_MODE) )
  55. {
  56. for(p=0;p<8;p++)
  57. {
  58. if (pByte > 127)
  59. {
  60. streamadd( buffer, oneBit, oneBitLength );
  61. }
  62. else
  63. {
  64. streamadd( buffer, zeroBit, zeroBitLength );
  65. }
  66. pByte = pByte<<1;
  67. }
  68. }
  69. else
  70. {
  71. streamadd( buffer, &pByte, 1 );
  72. }
  73. }
  74. void getPage(unsigned int page, int display)
  75. {
  76. if (display)
  77. {
  78. printf("%02x\b\b",page);
  79. }
  80. fseek(binFile,(long) page * 256,SEEK_SET);
  81. freadall(buffer,256,binFile);
  82. }
  83. unsigned char setVolume(unsigned int amplitude, int volume)
  84. {
  85. unsigned int tempval;
  86. if (amplitude > 128)
  87. {
  88. tempval = (unsigned int)floor(((amplitude - 128) * volume)/10 + 128);
  89. }
  90. else
  91. {
  92. tempval = (unsigned int)floor(128 - ((128 - amplitude) * volume/10));
  93. }
  94. return tempval;
  95. }
  96. void make16BitStereo(unsigned char *sineWave, unsigned char *sineWaveLength)
  97. {
  98. unsigned char oldSineWave[256];
  99. int i;
  100. for (i=0; i<*sineWaveLength; i++)
  101. {
  102. oldSineWave[i] = sineWave[i];
  103. }
  104. for (i=0; i<*sineWaveLength; i++)
  105. {
  106. sineWave[i*4] = 0;
  107. sineWave[i*4+1] = (oldSineWave[i]+0x80);
  108. sineWave[i*4+2] = 0;
  109. sineWave[i*4+3] = (oldSineWave[i]+0x80);
  110. }
  111. (*sineWaveLength) *= 4;
  112. }
  113. void setBankSwitchMode(char *pBankSwitch, int *bankSwitchMode)
  114. {
  115. int i;
  116. for (i=0; bankSwitchList[i][0] != '\0'; i++)
  117. {
  118. if (!strcasecmp(pBankSwitch,bankSwitchList[i]))
  119. {
  120. *bankSwitchMode = i;
  121. break;
  122. }
  123. }
  124. if (controlByteList[i] == 0)
  125. {
  126. fprintf(stderr,"Illegal bankswitch type!\n");
  127. exit(1);
  128. }
  129. }
  130. void createSineWave(unsigned char *bit, int bitLength, double volume, int wavType)
  131. {
  132. int i;
  133. int isOdd;
  134. int halfBitLength;
  135. if (volume < 0.10)
  136. {
  137. volume = 0.98;
  138. }
  139. else
  140. {
  141. volume /= 10;
  142. }
  143. if (wavType == SQUARE_WAVE)
  144. {
  145. halfBitLength = (int)(floor((float)bitLength)/2.0);
  146. isOdd = (int)(ceil((float)bitLength/2.0) - halfBitLength);
  147. for (i=0;i<halfBitLength;i++)
  148. {
  149. bit[i] = (unsigned char)floor(0xfc * volume);
  150. }
  151. if (isOdd)
  152. {
  153. bit[i++] = 0x80;
  154. }
  155. for (;i<bitLength;i++)
  156. {
  157. bit[i] = (unsigned char)floor(0x06 * volume);
  158. }
  159. }
  160. else /* SINE_WAV */
  161. {
  162. for (i=0; i<bitLength; i++)
  163. {
  164. bit[i] = (unsigned char)floor(((sin((((double)2 * (double)3.1415926535)/(double)bitLength)*(double)i)*volume + 1)*128));
  165. }
  166. }
  167. }
  168. int processParms( int argc, char *argv[], struct parmFlags *parms )
  169. {
  170. #if 0
  171. parms->control = 0;
  172. parms->sflag = 0;
  173. parms->kflag = 1;
  174. parms->wflag = SQUARE_WAVE;
  175. parms->stereoFlag = 0;
  176. parms->fflag = 1;
  177. parms->zeroBitLength = 0;
  178. parms->oneBitLength = 0;
  179. parms->aflag = 0;
  180. parms->dflag = DISPLAY_FILENAME;
  181. parms->mflag = 0;
  182. parms->pflag = 0;
  183. parms->vflag = 0;
  184. parms->volume = 0;
  185. parms->tflag = 'c';
  186. parms->multi = 0;
  187. parms->headerSeconds = (float)1.0;
  188. parms->clearingSeconds = (float)0.1;
  189. parms->hlength = 0;
  190. parms->bankSwitchMode = -1;
  191. parms->createMode = WAV_MODE;
  192. parms->audioDevName = 0;
  193. strcpy(parms->fullPath,"");
  194. strcpy(parms->wavFileName,"");
  195. #else
  196. memset( parms, 0, sizeof(*parms) );
  197. parms->kflag = 1;
  198. parms->wflag = SQUARE_WAVE;
  199. parms->fflag = -1;
  200. parms->dflag = DISPLAY_FILENAME;
  201. parms->tflag = 'c';
  202. parms->headerSeconds = (float)1.0;
  203. parms->clearingSeconds = (float)0.1;
  204. parms->bankSwitchMode = -1;
  205. parms->createMode = WAV_MODE;
  206. #endif
  207. while (--argc > 0 && (*++argv)[0] == '-')
  208. {
  209. char flag,
  210. cflag;
  211. cflag = 0;
  212. flag = *++argv[0];
  213. switch (flag)
  214. {
  215. case 'a':
  216. parms->aflag = 1;
  217. if( strlen((char*)(*argv)+1) > 0 )
  218. {
  219. parms->audioDevName = (char*)(*argv)+1;
  220. }
  221. break;
  222. case 'l':
  223. exit( palist() );
  224. case 'd':
  225. if (sscanf(*argv,"d%1d",&parms->dflag) == EOF)
  226. {
  227. fprintf(stderr,"Illegal detail level!\n");
  228. exit(1);
  229. }
  230. break;
  231. case 'p':
  232. parms->pflag = 1;
  233. break;
  234. case 'f':
  235. if (sscanf(*argv,"f%1d",&parms->fflag) == EOF)
  236. {
  237. fprintf(stderr,"Illegal .wav speed!\n");
  238. exit(1);
  239. }
  240. if (parms->fflag > 4)
  241. {
  242. parms->fflag = 4;
  243. }
  244. break;
  245. case 'b':
  246. if (!cflag)
  247. {
  248. setBankSwitchMode(*argv+1, &parms->bankSwitchMode);
  249. break;
  250. }
  251. case 'c':
  252. cflag = 1;
  253. if (strlen(*argv) != 3)
  254. {
  255. fprintf(stderr,"Illegal control byte value!\n");
  256. exit(1);
  257. }
  258. if (sscanf(*argv,"c%2x",&parms->control) == EOF)
  259. {
  260. fprintf(stderr,"Illegal control byte value!\n");
  261. exit(1);
  262. }
  263. printf("Control byte set to %02x\n",parms->control);
  264. break;
  265. case 'h':
  266. if (sscanf(*argv,"h%f",&parms->headerSeconds) == EOF)
  267. {
  268. fprintf(stderr,"Illegal header length!\n");
  269. exit(1);
  270. }
  271. if (parms->headerSeconds > 10 || parms->headerSeconds <=0)
  272. {
  273. printf("Bad header length!\n");
  274. exit(1);
  275. }
  276. break;
  277. case '0':
  278. if (sscanf(*argv,"0%d",&parms->zeroBitLength) == EOF)
  279. {
  280. fprintf(stderr,"Zero-bit length must be provided for 0 flag!\n");
  281. exit(1);
  282. }
  283. if (parms->zeroBitLength > 80 || parms->zeroBitLength <1)
  284. {
  285. fprintf(stderr,"Bad zero-bit length!\n");
  286. exit(1);
  287. }
  288. break;
  289. case '1':
  290. if (sscanf(*argv,"1%d",&parms->oneBitLength) == EOF)
  291. {
  292. printf("One-bit length must be provided for 0 flag!\n");
  293. exit(1);
  294. }
  295. if (parms->oneBitLength > 80 || parms->oneBitLength <1)
  296. {
  297. printf("Bad one-bit length!\n");
  298. exit(1);
  299. }
  300. break;
  301. case 'i':
  302. if (sscanf(*argv,"i%f",&parms->clearingSeconds) == EOF)
  303. {
  304. fprintf(stderr,"Illegal clearing tone length!\n");
  305. exit(1);
  306. }
  307. if (parms->clearingSeconds > 10 || parms->clearingSeconds <= 0.1)
  308. {
  309. fprintf(stderr,"Bad clearing tone length!\n");
  310. exit(1);
  311. }
  312. break;
  313. case 's':
  314. if (strlen(*argv) !=5)
  315. {
  316. fprintf(stderr,"Illegal start address!\n");
  317. exit(1);
  318. }
  319. {
  320. unsigned int start;
  321. if (sscanf(*argv,"s%04x",&start) == EOF)
  322. {
  323. fprintf(stderr,"Illegal start address!\n");
  324. exit(1);
  325. }
  326. parms->startHi = (start >> 8) & 0xff;
  327. parms->startLo = start & 0xff;
  328. }
  329. parms->sflag = 1;
  330. break;
  331. case 't':
  332. {
  333. int noValue = 0;
  334. if (sscanf(*argv,"t%c",&parms->tflag) == EOF)
  335. {
  336. noValue = 1;
  337. }
  338. if (noValue || (parms->tflag != 's' && parms->tflag != 'c'))
  339. {
  340. fprintf(stderr,"Type flag 't' must be 's' for Supercharger or 'c' for Cuttle Cart\n");
  341. exit(1);
  342. }
  343. }
  344. break;
  345. case 'w':
  346. if (sscanf(*argv,"w%1d",&parms->wflag) == EOF)
  347. {
  348. fprintf(stderr,"Illegal wave form type\n");
  349. exit(1);
  350. }
  351. if (parms->wflag > 1)
  352. {
  353. fprintf(stderr,"Illegal wave form type\n");
  354. exit(1);
  355. }
  356. break;
  357. case 'k':
  358. parms->kflag = 0;
  359. if (sscanf(*argv,"k%1d",&parms->kflag) == EOF)
  360. {
  361. fprintf(stderr,"Illegal .wav format!\n");
  362. exit(1);
  363. }
  364. if (parms->kflag < 0)
  365. {
  366. fprintf(stderr,"Illegal .wav format!\n");
  367. exit(1);
  368. }
  369. if (parms->kflag >= 2)
  370. {
  371. parms->kflag = 1;
  372. parms->stereoFlag = 1;
  373. }
  374. break;
  375. case 'o':
  376. if (sscanf(*argv,"o%s", &parms->wavFileName[0]) == EOF)
  377. {
  378. fprintf(stderr,"Output filename required for o flag\n");
  379. exit(1);
  380. }
  381. break;
  382. case 'm':
  383. if (strlen(*argv) != 3)
  384. {
  385. fprintf(stderr,"Illegal multi-byte value!\n");
  386. exit(1);
  387. }
  388. if (sscanf(*argv,"m%2x",&parms->multi) == EOF)
  389. {
  390. fprintf(stderr,"Illegal multi-byte value!\n");
  391. exit(1);
  392. }
  393. printf("Multi-load byte is $%02x\n",parms->multi);
  394. parms->mflag = 1;
  395. break;
  396. case 'r':
  397. parms->createMode = RAW_MODE;
  398. break;
  399. case 'v':
  400. if ((strlen(*argv) == 1) || (strlen(*argv)>3))
  401. {
  402. fprintf(stderr,"Illegal volume value, must be 1-10\n");
  403. exit(1);
  404. }
  405. parms->vflag = 1;
  406. if (sscanf(*argv,"v%2i",&parms->volume) == EOF)
  407. {
  408. fprintf(stderr,"Illegal volume value, must be 1-10\n");
  409. exit(1);
  410. }
  411. if ((((int)parms->volume < 1)) || ((int)parms->volume > 10))
  412. {
  413. fprintf(stderr,"Illegal volume value, must be 1-10\n");
  414. exit(1);
  415. }
  416. break;
  417. default :
  418. fprintf(stderr,"Unknown flag %c\n",flag);
  419. exit(1);
  420. break;
  421. }
  422. }
  423. parms->binFileCount = 0;
  424. parms->binFileQ = NULL;
  425. while (argc)
  426. {
  427. char tempFileName[256],
  428. extension[256],
  429. *tempPtr;
  430. strcpy(tempFileName, argv[0]);
  431. strtok(argv[0],".");
  432. tempPtr = strtok(NULL,"\0");
  433. if (tempPtr != 0)
  434. strcpy(extension,tempPtr);
  435. parms->binFileQ = addq(parms->binFileQ, tempFileName, &parms->binFileCount);
  436. ++argv;
  437. argc--;
  438. }
  439. if (parms->aflag)
  440. {
  441. /* direct audio audioput is hardcoded to 44kHz mono */
  442. parms->createMode = AUD_MODE;
  443. parms->stereoFlag = 0;
  444. parms->kflag = 1;
  445. }
  446. if( parms->fflag < 0 )
  447. {
  448. parms->fflag = ( parms->tflag == 'c' ) ? 1 : 0;
  449. }
  450. if (!parms->binFileCount)
  451. {
  452. printf( "Makewav " MAKEWAV_VERSION "\n"
  453. " Written By: Bob Colbert (rcolbert1@home.com)\n"
  454. " Direct Audio Support By: Sven Oliver Moll (svolli@svolli.de)\n"
  455. " Usage: makewav [flags] singleLd.bin [multiLd1[+multiLd2...+multiLdn]]\n"
  456. " Flags:\n"
  457. " -a<NAME> Output though audio device <NAME> (<NAME> is optional)\n"
  458. " (<NAME> allows trailing \"*\" as joker, first match is taken)\n"
  459. " -b<MODE> Set bankswitch mode:\n"
  460. " 2K,CV,4K,F8SC,28SC,F8,28,FE,3F,E0,FA,2A,3A,FANR,2ANR,\n"
  461. " 3ANR,F6SC,26SC,36SC,46SC,F6,26,36,46,E7,E7NR,F4SC,\n"
  462. " 24SC,34SC,44SC,F4,24,34,44,MB\n"
  463. " Where Fx and FxSC are Fx started in the first bank,\n"
  464. " and y8,y8SC,y6,y6SC,y4,y4SC are F8,F8SC,F6,F6SC,F4,\n"
  465. " F4SC resectively started in bank y.\n"
  466. " -cxx Set control byte (2 digit hex, overrides control byte\n"
  467. " determined by -b)\n"
  468. " -d# Diagnostics detail level (0 - 3)\n"
  469. " -f# Speed of load (0 - 4, Default=1 for CC, 0 for SC)\n"
  470. " -h# Set header tone length in seconds (default = 1.0)\n"
  471. " -i# Set clearing tone length in seconds (default = 0.1)\n"
  472. " -k Frequency: 0=22khz, 1(Default)=44khz, 2=16-bit stereo 44khz\n"
  473. " -l list available audio device names\n"
  474. " -mxx Set multiload byte (2 digit hex)\n"
  475. " -o Output File (Default = <singleLd.wav> or <multiLd1.wav>)\n"
  476. " -p Force \"blank pages\" to be transferred\n"
  477. " -r Create raw data file instead of a .wav file\n"
  478. " -sxxxx Set start address (4 digit hex)\n"
  479. " -t<TYPE> c=Cuttle Cart (Default) or s=Supercharger\n"
  480. " -v# Set volume level of .wav file (0.10-10 Default=0.98)\n"
  481. " -w# Wave form type: 0 (Default) for square or 1 for sine\n"
  482. " -0# Length of zero bit sine wave in bytes (overrides -f)\n"
  483. " -1# Length of one bit sine wave in bytes (overrides -f)\n" );
  484. exit(0);
  485. }
  486. return 0;
  487. }
  488. /*
  489. ** used for generating the CRC lookup table
  490. */
  491. dd crcrevhware(dd data, dd genpoly, dd accum)
  492. {
  493. int i;
  494. data <<= 1;
  495. for (i=8;i>0;i--)
  496. {
  497. data >>= 1;
  498. if ((data ^ accum) & 1)
  499. {
  500. accum = (accum >> 1) ^ genpoly;
  501. }
  502. else
  503. {
  504. accum >>= 1;
  505. }
  506. }
  507. return(accum);
  508. }
  509. /*
  510. ** init the CRC lookup table
  511. */
  512. void init_crc(void)
  513. {
  514. int i;
  515. for (i=0;i<256;i++)
  516. {
  517. crctab[i] = crcrevhware(i,CRC32_REV,0);
  518. }
  519. }
  520. /*
  521. ** update CRC
  522. */
  523. void ucrc(unsigned char data)
  524. {
  525. crc = (crc >> 8) ^ crctab[(crc ^ data) & 0xff];
  526. }
  527. db Lookup(dd *table)
  528. {
  529. // dd t;
  530. int i = 0;
  531. while(table[i] != -1)
  532. {
  533. if (table[i] == crc)
  534. return i;
  535. i++;
  536. }
  537. return -1;
  538. /*
  539. while(1)
  540. {
  541. t = *table++;
  542. if (t == -1) return(0);
  543. if (t == crc)
  544. {
  545. if (table == BS_3)
  546. printf("- %s",BS_3_DESC[i]);
  547. return(1);
  548. }
  549. i++;
  550. }
  551. */
  552. }
  553. void clearMeter(int meterMax)
  554. {
  555. int i;
  556. printf("%*s",meterMax+2," ");
  557. for (i=0; i<meterMax+2; i++)
  558. {
  559. printf("\b");
  560. }
  561. // printf("%*s",meterMax+2,"\b");
  562. }
  563. void drawMeter(int current, int max, int meterMax)
  564. {
  565. int i,
  566. meterLength;
  567. meterLength = (int)((float)current/(float)(max-1)*meterMax);
  568. printf("[");
  569. for (i=0; i<meterMax; i++)
  570. {
  571. if (i<meterLength)
  572. {
  573. printf("*");
  574. }
  575. else
  576. {
  577. printf("-");
  578. }
  579. }
  580. printf("]");
  581. for (i=0; i<meterMax+2; i++)
  582. {
  583. printf("\b");
  584. }
  585. }
  586. int main( int argc, char *argv[] )
  587. {
  588. int i = 0,
  589. j = 0,
  590. k = 0,
  591. filecount = 0,
  592. gamePageCount = 0,
  593. scflag = 0,
  594. file_page_count = 0,
  595. currentBinFile = 0,
  596. bytesPerSecond = 0;
  597. unsigned char
  598. controlByte = 0,
  599. in_byte = 0,
  600. multiByte = 0,
  601. speedLow = 0,
  602. speedHi = 0;
  603. unsigned int
  604. length_lword[4],
  605. sum = 0,
  606. page = 0,
  607. init_bank = 0;
  608. char pg_bank_byte = 0;
  609. long fsize = 0;
  610. struct parmFlags parms;
  611. char full_path_buffer[256];
  612. streambuffer_t streambuffer;
  613. streaminit( &streambuffer );
  614. processParms(argc, argv, &parms);
  615. if (parms.zeroBitLength)
  616. {
  617. zeroBitLength = parms.zeroBitLength;
  618. }
  619. else
  620. {
  621. zeroBitLength = bitLength[parms.fflag][parms.kflag][0];
  622. }
  623. if (parms.oneBitLength)
  624. {
  625. oneBitLength = parms.oneBitLength;
  626. }
  627. else
  628. {
  629. oneBitLength = bitLength[parms.fflag][parms.kflag][1];
  630. }
  631. createSineWave(clearingTone, clearingToneLength[parms.kflag],parms.volume, SINE_WAVE);
  632. createSineWave(zeroBit,zeroBitLength, parms.volume, parms.wflag);
  633. createSineWave(oneBit,oneBitLength, parms.volume, parms.wflag);
  634. /* 0x55 sends 4 "01" bit combinations so the formula to calculate the header length is */
  635. /* floor((samples per second/bytes per "01" sample)/4) */
  636. bytesPerSecond = (int)(((parms.kflag == 0)?22050:44100)/(oneBitLength+zeroBitLength))/4;
  637. parms.hlength = (float)floor(parms.headerSeconds * bytesPerSecond);
  638. if (parms.stereoFlag)
  639. {
  640. make16BitStereo(clearingTone, &(clearingToneLength[1]));
  641. make16BitStereo(zeroBit, &zeroBitLength);
  642. make16BitStereo(oneBit, &oneBitLength);
  643. }
  644. scflag = 0;
  645. currentBinFile = 0;
  646. if (parms.binFileCount > 4)
  647. {
  648. char answer;
  649. fprintf(stderr,"Warning! %d .wav files will be created, Continue? (Y/N)", parms.binFileCount);
  650. while( scanf("%c",&answer) < 1 )
  651. {
  652. if (answer != 'y' && answer != 'Y')
  653. {
  654. exit(1);
  655. }
  656. }
  657. }
  658. if (parms.dflag >= DISPLAY_FILENAME)
  659. {
  660. printf("Converting %d file%s for use with the %s:\n",
  661. parms.binFileCount, (parms.binFileCount > 1)?"s":"",
  662. (parms.tflag == 's')?"Supercharger":"Cuttle Cart");
  663. printf(" Using %s %skhz ",(parms.stereoFlag)?"16-bit stereo":"8-bit mono",(parms.kflag == 0)?"22":"44");
  664. printf( parms.aflag ? "direct audio": ".wav format");
  665. printf(" with a %0.2f second header tone\n",parms.headerSeconds);
  666. printf(" (zero bit/one bit) lengths = (%d/%d)", zeroBitLength/((parms.stereoFlag)?4:1), oneBitLength/((parms.stereoFlag)?4:1));
  667. printf(" implemented with %s wave forms\n",(parms.wflag == 0)?"square":"sine");
  668. }
  669. while (parms.binFileQ != NULL)
  670. {
  671. int bankSwitchMode = -1;
  672. char *sourceFileName;
  673. char parmEntry[256];
  674. char baseFileName[256];
  675. int multiLoad;
  676. if (parms.dflag >= DISPLAY_FILENAME)
  677. {
  678. printf("%s -> ",parms.binFileQ->fileName);
  679. }
  680. filecount = 0;
  681. flength = 0;
  682. wavFlength = 0;
  683. strcpy(parmEntry, parms.binFileQ->fileName);
  684. strcpy(baseFileName, strtok(parms.binFileQ->fileName,".+"));
  685. if (!strcmp(parms.wavFileName,""))
  686. {
  687. snprintf(&parms.wavFileName[0], sizeof(parms.wavFileName)-1, "%s.wav", baseFileName);
  688. }
  689. sourceFileName = strtok(parmEntry,"+");
  690. wavFile = 0;
  691. multiLoad = 0;
  692. while (sourceFileName != NULL)
  693. {
  694. page = 0;
  695. if ((binFile = fopen(sourceFileName,"rb")) == NULL)
  696. {
  697. fprintf(stderr,"ERROR: unable to open .bin file %s\n",sourceFileName);
  698. exit(1);
  699. }
  700. fseek(binFile,0,SEEK_END);
  701. fsize = ftell(binFile);
  702. fseek(binFile,0,SEEK_SET);
  703. freadall(fileBuffer,fsize,binFile);
  704. if (parms.tflag == 's' && fsize != 8448 && fsize != 6144 && fsize != 2048 && fsize != 4096 && fsize != 32767)
  705. {
  706. fprintf(stderr,"Invalid file size for Supercharger, skipping\n");
  707. break;
  708. }
  709. if (!wavFile && (parms.createMode != AUD_MODE) )
  710. {
  711. strcpy(full_path_buffer, parms.wavFileName);
  712. if ((wavFile = fopen(full_path_buffer,"wb")) == NULL)
  713. {
  714. fprintf(stderr,"ERROR: unable to create wavFile %s\n",full_path_buffer);
  715. exit(1);
  716. }
  717. if (parms.dflag >= DISPLAY_FILENAME)
  718. {
  719. printf("%s",full_path_buffer);
  720. }
  721. }
  722. /* Write .wav header */
  723. if (parms.createMode == WAV_MODE && !multiLoad)
  724. {
  725. for(k=0;k<44;k++)
  726. {
  727. fputc(header[parms.kflag + parms.stereoFlag][k],wavFile);
  728. }
  729. }
  730. multiByte = 0;
  731. init_bank = 0;
  732. /* For original supercharger only */
  733. if (parms.tflag == 's')
  734. {
  735. if (fsize == 2048)
  736. {
  737. init_bank = 2;
  738. }
  739. else if (fsize == 4096)
  740. {
  741. init_bank = 1;
  742. }
  743. }
  744. scflag = 0;
  745. /* Check for 32k Supercharger games */
  746. if (fsize == 0x7FFF)
  747. {
  748. scflag = 1;
  749. }
  750. if (fsize == 6144 || fsize == 8448 || scflag)
  751. {
  752. /* This is the control byte, it determines the bankswitching mode of the SC
  753. Bits Function
  754. ------ --------
  755. D7-D5 Write Pulse Delay (Set to 0)
  756. D4-D2 RAM/ROM Configuration
  757. Value $f000 $f800
  758. ----- ----- -----
  759. 000 3 ROM
  760. 001 1 ROM
  761. 010 3 1
  762. 011 1 3
  763. 100 3 ROM
  764. 101 2 ROM
  765. 110 3 2
  766. 111 2 3
  767. */
  768. if (!parms.control)
  769. {
  770. controlByte = 0x0d; /* %00001101 */
  771. }
  772. speedLow = 0x42;
  773. speedHi = 0x02;
  774. file_page_count = 24;
  775. if (fsize >= 8448)
  776. {
  777. getPage(32,0);
  778. if (!parms.sflag)
  779. {
  780. parms.startLo=buffer[0];
  781. parms.startHi=buffer[1];
  782. }
  783. // parms.sflag = 1;
  784. if (!parms.control)
  785. {
  786. controlByte = buffer[2];
  787. }
  788. file_page_count = buffer[3];
  789. scflag = 1;
  790. for (i=0;i<0x18;i++)
  791. {
  792. pageList[i] = buffer[0x10+i];
  793. }
  794. multiByte = buffer[5];
  795. }
  796. }
  797. else
  798. {
  799. int i;
  800. /* Find file size in list */
  801. for (i=0; fileSizeList[i] != 0; i++)
  802. {
  803. if (fsize == fileSizeList[i])
  804. {
  805. /* if the bank-switch mode wasn't set in the parms, use default */
  806. if (parms.bankSwitchMode < 0)
  807. {
  808. bankSwitchMode = i;
  809. }
  810. else if (fileSizeList[parms.bankSwitchMode] != fsize)
  811. {
  812. fprintf(stderr,"Bankswitch scheme %s is not legal for a %dK ROM\n",
  813. bankSwitchList[parms.bankSwitchMode],
  814. (int)(fsize/1024));
  815. exit(1);
  816. }
  817. else /* bank-switch mode was set in the parms */
  818. {
  819. bankSwitchMode = parms.bankSwitchMode;
  820. }
  821. break;
  822. }
  823. }
  824. if (fileSizeList[i] == 0)
  825. {
  826. fprintf(stderr, "ERROR! Source .bin file must be 2048, 4096, 6144, 8192, 8448, 12228, 16384, 32768, or 65536 bytes\n");
  827. exit(1);
  828. }
  829. file_page_count = fileSizeList[bankSwitchMode] / 256;
  830. }
  831. gamePageCount = 0;
  832. for(i=0;i<file_page_count;i++)
  833. {
  834. getPage(i,0);
  835. emptyPage[i] = 1;
  836. for (j=0;j<255;j++)
  837. {
  838. if (buffer[j] != buffer[j+1])
  839. {
  840. emptyPage[i] = 0;
  841. }
  842. }
  843. if (!emptyPage[i])
  844. {
  845. gamePageCount++;
  846. }
  847. }
  848. speedHi = gamePageCount/21 + 1;
  849. speedLow = gamePageCount*256/21 - (speedHi-1)*256;
  850. /*Write low frequency clearing tone*/
  851. if (!multiLoad)
  852. {
  853. float sineCount;
  854. sineCount = (float)floor(parms.clearingSeconds * (((parms.kflag == 0)?22050:44100)/(clearingToneLength[parms.kflag])));
  855. if (parms.stereoFlag)
  856. {
  857. sineCount /= 2;
  858. }
  859. for(k=0;k<sineCount;k++)
  860. {
  861. streamadd( &streambuffer, &clearingToneLength[parms.kflag], 1 );
  862. }
  863. }
  864. /* Write game header tone, just a series of alternating zero and one bits */
  865. for(k=1;k<(parms.hlength);k++)
  866. {
  867. processByte( &streambuffer, 0x55, parms.createMode );
  868. }
  869. /* Two zero bits in a row indicate the beginning of the data */
  870. processByte( &streambuffer, 0x54, parms.createMode );
  871. if (parms.bankSwitchMode < 0 )
  872. {
  873. int i;
  874. crc = 0 ;
  875. init_crc();
  876. for (i=0; i<fsize; i++)
  877. ucrc(fileBuffer[i]) ;
  878. switch(fsize)
  879. {
  880. case 0x800:
  881. if ((i=Lookup(BS_1)) >= 0)
  882. {
  883. bankSwitchMode = BSM_CV; /* CommaVid */
  884. if (parms.dflag >= DISPLAY_FILENAME)
  885. printf("- %s",BS_1_DESC[i]);
  886. }
  887. break;
  888. case 0x2000:
  889. for (i=0; i<2; i++)
  890. {
  891. for (j=0; j<256; j++)
  892. {
  893. if (fileBuffer[0] != fileBuffer[i * 0x1000 + j])
  894. {
  895. bankSwitchMode = BSM_28;
  896. }
  897. }
  898. }
  899. if ((i=Lookup(BS_3)) >= 0)
  900. {
  901. bankSwitchMode = BSM_E0; /* Parker Brothers */
  902. if (parms.dflag >= DISPLAY_FILENAME)
  903. {
  904. printf("- %s",BS_3_DESC[i]);
  905. }
  906. }
  907. if ((i=Lookup(BS_4)) >= 0)
  908. {
  909. bankSwitchMode = BSM_3F; /* Tigervision */
  910. if (parms.dflag >= DISPLAY_FILENAME)
  911. {
  912. printf("- %s",BS_4_DESC[i]);
  913. }
  914. }
  915. if ((i=Lookup(BS_5)) >= 0)
  916. {
  917. bankSwitchMode = BSM_FE; /* Activision 8K flat model */
  918. if (parms.dflag >= DISPLAY_FILENAME)
  919. {
  920. printf("- %s",BS_5_DESC[i]);
  921. }
  922. }
  923. if ((i=Lookup(BS_9)) >= 0)
  924. {
  925. bankSwitchMode = BSM_F8; /* Atari F8 Start in Bank 1 */
  926. if (parms.dflag >= DISPLAY_FILENAME)
  927. {
  928. printf("- %s",BS_9_DESC[i]);
  929. }
  930. }
  931. break;
  932. case 0x4000:
  933. for (i=0; i<4; i++)
  934. {
  935. for (j=0; j<256; j++)
  936. {
  937. if (fileBuffer[0] != fileBuffer[i * 0x1000 + j])
  938. {
  939. bankSwitchMode = BSM_46 ;
  940. }
  941. }
  942. }
  943. if ((i=Lookup(BS_6)) >= 0)
  944. {
  945. bankSwitchMode = BSM_46SC; /* 16K Superchip that can't be recognized automatically */
  946. if (parms.dflag >= DISPLAY_FILENAME)
  947. {
  948. printf("- %s",BS_6_DESC[i]);
  949. }
  950. }
  951. if ((i=Lookup(BS_7)) >= 0)
  952. {
  953. bankSwitchMode = BSM_E7; /* M Network 16K */
  954. if (parms.dflag >= DISPLAY_FILENAME)
  955. {
  956. printf("- %s",BS_7_DESC[i]);
  957. }
  958. }
  959. break;
  960. case 0x8000:
  961. for (i=0; i<8; i++)
  962. {
  963. for (j=0; j<256; j++)
  964. {
  965. if (fileBuffer[0] != fileBuffer[i * 0x1000 + j])
  966. {
  967. bankSwitchMode = BSM_F4;
  968. }
  969. }
  970. }
  971. break;
  972. case 0x10000:
  973. if (bankSwitchMode == BSM_MB)
  974. {
  975. parms.pflag = 1;
  976. printf("Forcing blank pages to be transferred for\n");
  977. printf("bankswitch mode MB\n");
  978. }
  979. break;
  980. }
  981. }
  982. if (parms.pflag)
  983. {
  984. gamePageCount = file_page_count;
  985. }
  986. if (parms.control)
  987. {
  988. controlByte = parms.control;
  989. }
  990. else if (parms.tflag == 's')
  991. {
  992. if (!scflag)
  993. controlByte = 0x1d;
  994. if (fsize == 2048)
  995. {
  996. getPage(startPageList[bankSwitchMode],0);
  997. if (buffer[0xfd] < 0xf8)
  998. {
  999. controlByte = 0x09;
  1000. }
  1001. }
  1002. }
  1003. else if (!scflag)
  1004. {
  1005. controlByte = controlByteList[bankSwitchMode];
  1006. }
  1007. /* The first two bytes of data indicate the beginning address of the code */
  1008. if ((!parms.sflag) && !scflag)
  1009. {
  1010. getPage(startPageList[bankSwitchMode],0);
  1011. parms.startLo = buffer[0xfc];
  1012. parms.startHi = buffer[0xfd];
  1013. }
  1014. processByte( &streambuffer, parms.startLo, parms.createMode );
  1015. processByte( &streambuffer, parms.startHi, parms.createMode );
  1016. processByte( &streambuffer, controlByte, parms.createMode );
  1017. /* Number of pages to load */
  1018. processByte( &streambuffer, (unsigned char)(gamePageCount), parms.createMode );
  1019. /* Game header checksum -- first 8 bytes must add up to 0x55 */
  1020. if( parms.mflag )
  1021. {
  1022. multiByte = parms.multi;
  1023. }
  1024. processByte( &streambuffer, (unsigned char)(0x55 - parms.startLo - parms.startHi - multiByte - controlByte - gamePageCount - speedLow - speedHi), parms.createMode );
  1025. processByte( &streambuffer, multiByte, parms.createMode );
  1026. processByte( &streambuffer, speedLow, parms.createMode );
  1027. processByte( &streambuffer, speedHi, parms.createMode );
  1028. if( parms.dflag >= DISPLAY_FILENAME )
  1029. {
  1030. printf("\n");
  1031. }
  1032. if( parms.dflag >= DISPLAY_SUMMARY )
  1033. {
  1034. printf(" Bankswitch type = ");
  1035. if (scflag)
  1036. {
  1037. printf("Supercharger\n");
  1038. }
  1039. else
  1040. {
  1041. printf("%s\n",bankSwitchList[bankSwitchMode]);
  1042. }
  1043. printf(" File size = %-5ld",fsize);
  1044. printf(" Start address = $%02x%02x\n",parms.startHi,parms.startLo);
  1045. printf(" Multi-Load byte = $%2.2x Page count = $%2.2x\n",(unsigned char) multiByte,(unsigned char) gamePageCount);
  1046. printf(" Control-byte = $%2.2x Blank pages = $%2.2x\n",(unsigned char) controlByte,(unsigned char) (file_page_count - gamePageCount));
  1047. }
  1048. while ((int)page < file_page_count)
  1049. {
  1050. int j;
  1051. /* Get appropriate page */
  1052. if (!emptyPage[page] || parms.pflag)
  1053. {
  1054. getPage(page,0);
  1055. if (parms.dflag >= DISPLAY_FILENAME && parms.dflag < DISPLAY_DETAILS)
  1056. drawMeter(page, gamePageCount, METER_LENGTH);
  1057. }
  1058. /* If we just got the page, put the page header which consists of two bytes. The first byte */
  1059. /* is a counter that begins at zero for the first page and is incremented by 4 for each */
  1060. /* subsequent page. If the value is greater than 0x1f, then 0x1f is subtracted from it. */
  1061. if (scflag)
  1062. {
  1063. pg_bank_byte = pageList[page];
  1064. }
  1065. else
  1066. {
  1067. pg_bank_byte = (page % 8) * 4 + init_bank + (int)floor((page-(int)floor(page/32)*32)/8) + (int)floor(page/32) * 32;
  1068. }
  1069. sum = 0;
  1070. /* Get the sum of all 256 bytes of the current page */
  1071. for(j=0;j<256;j++)
  1072. {
  1073. sum += (char) buffer[j];
  1074. }
  1075. /* The second byte of the page header is 0x55 - the first byte - the sum of the 256 bytes of */
  1076. /* program data. */
  1077. in_byte = (char) (0x55 - pg_bank_byte - sum);
  1078. /* Put the program data */
  1079. if (!emptyPage[page] || parms.pflag)
  1080. {
  1081. if (parms.dflag >= DISPLAY_DETAILS)
  1082. {
  1083. printf(" - bank %2.2d, page %2.2d, page&bank byte %2.2x, checksum %2.2x\n",(int)(pg_bank_byte&0x3) + (int)(pg_bank_byte&0xE0)/8,
  1084. (int)((pg_bank_byte & 0x1c)/4),(unsigned char)pg_bank_byte,
  1085. (unsigned char)in_byte);
  1086. }
  1087. processByte( &streambuffer, pg_bank_byte,parms.createMode);
  1088. processByte( &streambuffer, in_byte,parms.createMode);
  1089. for(j=0;j<256;j++)
  1090. {
  1091. processByte( &streambuffer, buffer[j],parms.createMode);
  1092. }
  1093. }
  1094. /* Done with this page, increment page counter */
  1095. page++;
  1096. /* printf("\nPage is = %d",page); */
  1097. }
  1098. /* We are done, put a tone at the end of the game, unnecessary, but a nice touch */
  1099. fclose(binFile);
  1100. filecount++;
  1101. sourceFileName = strtok(NULL,"+");
  1102. if (sourceFileName != NULL)
  1103. {
  1104. for(k=1;k<parms.headerSeconds * bytesPerSecond * 2;k++)
  1105. {
  1106. processByte( &streambuffer, 0x55,parms.createMode);
  1107. }
  1108. multiLoad = 1;
  1109. }
  1110. else
  1111. for(k=1;k<bytesPerSecond/2;k++)
  1112. {
  1113. processByte( &streambuffer, 0x55,parms.createMode);
  1114. }
  1115. } /* End of strtok While */
  1116. if ((parms.createMode == WAV_MODE) && wavFile)
  1117. {
  1118. /* Determine the file length for the WAV chunk of the .wav file */
  1119. flength = streambuffer.used;
  1120. wavFlength = flength + 36;
  1121. /* Write the file length in hi-byte/lo-byte, hi-word/lo-word format to the .wav file */
  1122. fseek(wavFile,0x28,SEEK_SET);
  1123. length_lword[3] = 0;
  1124. length_lword[2] = 0;
  1125. length_lword[1] = 0;
  1126. if (flength > 16777216)
  1127. {
  1128. length_lword[3] = (int)floor(flength / 16777216);
  1129. flength -= length_lword[3] * 16777216;
  1130. }
  1131. if (flength > 65535)
  1132. {
  1133. length_lword[2] = (int)floor(flength / 65536);
  1134. flength -= length_lword[2] * 65536;
  1135. }
  1136. if (flength > 255)
  1137. {
  1138. length_lword[1] = (int)floor(flength / 256);
  1139. flength -= length_lword[1] * 256;
  1140. }
  1141. length_lword[0] = (unsigned int)flength;
  1142. for(i=0;i<4;i++)
  1143. {
  1144. fputc(length_lword[i],wavFile);
  1145. }
  1146. /* The file length for the RIFF chunk of the .wav file is in wavFlength */
  1147. /* Write the file length in hi-byte/lo-byte, hi-word/lo-word format to the .wav file */
  1148. fseek(wavFile,0x04,SEEK_SET);
  1149. length_lword[3] = 0;
  1150. if (wavFlength > 65535)
  1151. {
  1152. length_lword[2] = (unsigned int)floor(wavFlength / 65536);
  1153. wavFlength -= length_lword[2] * 65536;
  1154. }
  1155. if (wavFlength > 256)
  1156. {
  1157. length_lword[1] = (unsigned int)floor(wavFlength / 256);
  1158. wavFlength -= length_lword[1] * 256;
  1159. }
  1160. length_lword[0] = (unsigned int)wavFlength;
  1161. for(i=0;i<4;i++)
  1162. {
  1163. fputc(length_lword[i],wavFile);
  1164. }
  1165. fseek(wavFile,0x2C,SEEK_SET);
  1166. }
  1167. if (wavFile)
  1168. {
  1169. fwrite( streambuffer.start, streambuffer.used, 1, wavFile );
  1170. fflush( wavFile );
  1171. fclose( wavFile );
  1172. }
  1173. if( parms.aflag )
  1174. {
  1175. paplay( streambuffer.start, streambuffer.used, parms.audioDevName );
  1176. }
  1177. strcpy(parms.wavFileName,"");
  1178. currentBinFile++;
  1179. parms.binFileQ = delq(parms.binFileQ);
  1180. if (parms.dflag >= DISPLAY_FILENAME && parms.dflag < DISPLAY_DETAILS)
  1181. {
  1182. clearMeter(METER_LENGTH);
  1183. }
  1184. }
  1185. streamclean( &streambuffer );
  1186. return 0;
  1187. }