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.

392 lines
10KB

  1. /*
  2. ** All my chip simulator noobits. But remember this is just me screwing around.
  3. */
  4. #include <math.h>
  5. #include <iostream>
  6. #include <vector>
  7. namespace ChipSym
  8. {
  9. class CPUStepper
  10. {
  11. private:
  12. int sampleRateInHz;
  13. double chipFrequencyInMHZ;
  14. unsigned int ticksPerSample;
  15. double tickFractionPerSample;
  16. double accruedTickFraction;
  17. public:
  18. CPUStepper( unsigned int _sampleRateInHz, double _chipFrequencyInMHZ )
  19. : sampleRateInHz( _sampleRateInHz ), chipFrequencyInMHZ( _chipFrequencyInMHZ ), accruedTickFraction( 0 )
  20. {
  21. double tpsD = chipFrequencyInMHZ * 1000000 / sampleRateInHz;
  22. double tpsdi;
  23. tickFractionPerSample = modf( tpsD, &tpsdi );
  24. ticksPerSample = (unsigned int)tpsdi;
  25. }
  26. /*
  27. ** Take one step and tell me how many CPU ticks I would have seen if I am sampling at sampleRate.
  28. ** This won't be a constant of course since sometimes we get an extra to catch up
  29. */
  30. unsigned int nextStepCPUTicks()
  31. {
  32. accruedTickFraction += tickFractionPerSample;
  33. if( accruedTickFraction > 1 )
  34. {
  35. accruedTickFraction -= 1;
  36. return ticksPerSample + 1;
  37. }
  38. return ticksPerSample;
  39. }
  40. };
  41. static double NESNTSCCPURate = 1.789773;
  42. class NESBase
  43. {
  44. protected:
  45. int digWavelength; // this is the 2^11 which sets frequency time
  46. int t, currPos;
  47. float wfMin, wfMax, wfMinToMax;
  48. public:
  49. NESBase( float imin, float imax )
  50. :
  51. wfMin( imin ), wfMax( imax )
  52. {
  53. digWavelength = 1 << 7; // Callibrate this later
  54. t = digWavelength;
  55. currPos = 0;
  56. wfMinToMax = wfMax - wfMin;
  57. }
  58. void setDigWavelength( int df ) // 0 -> 2^11
  59. {
  60. digWavelength = df;
  61. }
  62. };
  63. class NESTriangle : public NESBase // http://wiki.nesdev.com/w/index.php/APU_Triangle
  64. {
  65. protected:
  66. float waveForm[ 32 ];
  67. CPUStepper cpu;
  68. public:
  69. NESTriangle( float imin, float imax, unsigned int sampleRate )
  70. :
  71. NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate )
  72. {
  73. for( int i=0; i<16; ++i ) {
  74. waveForm[ 15 - i ] = i / 15.0f;
  75. waveForm[ 16 + i ] = i / 15.0f;
  76. }
  77. }
  78. float step()
  79. {
  80. int ticks = cpu.nextStepCPUTicks();
  81. t -= ticks;
  82. if( t < 0 )
  83. {
  84. currPos ++;
  85. t += digWavelength;
  86. if( currPos >= 32 ) currPos = 0;
  87. }
  88. return waveForm[ currPos ] * wfMinToMax + wfMin;
  89. }
  90. void setWavelengthInSeconds( float seconds )
  91. {
  92. setDigWavelength( (unsigned int)( seconds * NESNTSCCPURate * 1000 * 1000 / 32 ) );
  93. }
  94. };
  95. class NESArbitraryWaveform : public NESTriangle {
  96. public:
  97. NESArbitraryWaveform( float imin, float imax, unsigned int sampleRate ) : NESTriangle( imin, imax, sampleRate ) { }
  98. void setWaveformPoint( unsigned int pos, // 0->31
  99. unsigned int val ) // 0->15
  100. {
  101. waveForm[ pos ] = val / 15.0f;
  102. }
  103. unsigned int getWaveformPoint( unsigned int pos ) { return waveForm[ pos ] * 15.0f; }
  104. };
  105. class NESPulse : public NESBase // http://wiki.nesdev.com/w/index.php/APU_Pulse
  106. {
  107. private:
  108. int dutyCycle;
  109. float **waveForms;
  110. int nDutyCycles;
  111. int wfLength;
  112. CPUStepper cpu;
  113. public:
  114. NESPulse( float imin, float imax, int sampleRate )
  115. :
  116. NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate / 2 )
  117. {
  118. wfLength = 8;
  119. nDutyCycles = 4;
  120. dutyCycle = 1;
  121. waveForms = new float*[ 4 ];
  122. for( int i=0; i<nDutyCycles; ++i )
  123. {
  124. waveForms[ i ] = new float[ wfLength ];
  125. for (int j=0; j<wfLength; ++j ) waveForms[ i ][ j ] = ( i == nDutyCycles - 1 ) ? 1 : 0;
  126. // Really, read that website for this stuff.
  127. switch( i )
  128. {
  129. case 0:
  130. waveForms[ i ][ 1 ] = 1;
  131. break;
  132. case 1:
  133. waveForms[ i ][ 1 ] = 1;
  134. waveForms[ i ][ 2 ] = 1;
  135. break;
  136. case 2:
  137. waveForms[ i ][ 1 ] = 1;
  138. waveForms[ i ][ 2 ] = 1;
  139. waveForms[ i ][ 3 ] = 1;
  140. waveForms[ i ][ 4 ] = 1;
  141. break;
  142. case 3:
  143. waveForms[ i ][ 1 ] = 0;
  144. waveForms[ i ][ 2 ] = 0;
  145. break;
  146. }
  147. }
  148. }
  149. void setWavelengthInSeconds( float seconds )
  150. {
  151. setDigWavelength( (unsigned int)( seconds * NESNTSCCPURate * 1000 * 1000 / 2.0 / 8.0) );
  152. }
  153. void setDutyCycle( int dc )
  154. {
  155. dutyCycle = dc;
  156. }
  157. float step()
  158. {
  159. int ticks = cpu.nextStepCPUTicks();
  160. t -= ticks;
  161. if( t < 0 )
  162. {
  163. currPos ++;
  164. t += digWavelength;
  165. if( currPos >= wfLength ) currPos = 0;
  166. }
  167. return waveForms[ dutyCycle ][ currPos ] * wfMinToMax + wfMin;
  168. }
  169. };
  170. class NESNoise : public NESBase
  171. {
  172. public:
  173. typedef enum ShortPeriods
  174. {
  175. SHORT_31,
  176. SHORT_93
  177. } ShortPeriods;
  178. private:
  179. CPUStepper cpu;
  180. unsigned short shiftRegister;
  181. unsigned short currentOutput;
  182. unsigned short xorBit;
  183. unsigned short curr93key;
  184. std::vector< unsigned short > starts_for_93s;
  185. ShortPeriods currShortPeriods;
  186. public:
  187. NESNoise( float imin, float imax, int sampleRate )
  188. :
  189. NESBase( imin, imax ), cpu( sampleRate, NESNTSCCPURate / 2 )
  190. {
  191. setPeriod( 8 );
  192. shiftRegister = 0x07;
  193. currentOutput = shiftRegister & 1;
  194. xorBit = 1;
  195. curr93key = 17;
  196. init93();
  197. currShortPeriods = SHORT_93;
  198. }
  199. void init93()
  200. {
  201. // To generate this, see ../standalone/chipNoisePeriod.cpp
  202. unsigned short calc_start_for_93s[] = {
  203. 1, 3, 5, 7, 11, 13, 15, 17, 19, 21, 23, 25, 29, 31, 33,
  204. 35, 37, 39, 41, 43, 47, 49, 51, 53, 55, 57, 59, 61, 66, 68,
  205. 70, 74, 76, 78, 80, 84, 86, 88, 90, 92, 94, 96, 98, 102, 104,
  206. 106, 108, 110, 112, 114, 116, 120, 122, 124, 126, 129, 131, 133, 135, 139,
  207. 141, 143, 145, 147, 149, 151, 153, 157, 159, 161, 163, 165, 167, 169, 171,
  208. 175, 177, 179, 181, 183, 185, 187, 189, 194, 196, 198, 200, 202, 204, 206,
  209. 208, 212, 214, 218, 220, 222, 224, 226, 230, 232, 234, 236, 238, 240, 242,
  210. 244, 248, 250, 252, 254, 259, 263, 267, 271, 273, 275, 277, 279, 281, 285,
  211. 287, 291, 295, 299, 303, 305, 307, 309, 311, 313, 315, 317, 322, 326, 330,
  212. 334, 336, 340, 342, 344, 346, 348, 350, 354, 358, 362, 366, 368, 370, 372,
  213. 376, 378, 380, 382, 387, 389, 395, 397, 399, 401, 403, 405, 407, 409, 413,
  214. 415, 417, 419, 421, 423, 425, 427, 431, 435, 437, 443, 445, 450, 452, 454,
  215. 456, 458, 460, 464, 468, 470, 472, 474, 478, 482, 486, 488, 490, 492, 494,
  216. 498, 500, 506, 535, 543, 547, 551, 555, 559, 563, 565, 571, 573, 598, 606,
  217. 610, 614, 618, 622, 626, 628, 634, 636, 645, 647, 653, 655, 661, 663, 669,
  218. 671, 673, 677, 679, 681, 687, 689, 691, 693, 699, 701, 710, 716, 718, 724,
  219. 726, 732, 734, 742, 744, 750, 752, 756, 760, 762, 764, 775, 779, 785, 787,
  220. 789, 793, 797, 799, 803, 811, 815, 819, 821, 823, 827, 829, 834, 838, 842,
  221. 852, 858, 860, 862, 870, 874, 880, 882, 884, 888, 892, 894, 901, 907, 913,
  222. 915, 919, 927, 931, 933, 935, 947, 962, 970, 982, 988, 990, 994, 1000, 1004,
  223. 1012, 1018, 1057, 1059, 1061, 1063, 1065, 1067, 1075, 1077, 1079, 1081, 1083, 1100, 1110,
  224. 1116, 1130, 1132, 1134, 1138, 1144, 1185, 1187, 1189, 1191, 1195, 1201, 1209, 1211, 1228,
  225. 1238, 1244, 1264, 1274, 1293, 1311, 1313, 1335, 1354, 1392, 1415, 1419, 1425, 1455, 1467,
  226. 1510, 1524, 1569, 1620, 1638, 1671, 1868, 0 };
  227. unsigned short* curr = calc_start_for_93s;
  228. while( *curr != 0 )
  229. {
  230. starts_for_93s.push_back( *curr );
  231. ++curr;
  232. }
  233. }
  234. void set93Key( int sp )
  235. {
  236. if( sp != curr93key )
  237. {
  238. setRegister( starts_for_93s[ sp ] );
  239. }
  240. curr93key = sp;
  241. }
  242. void setModeFlag( bool mf )
  243. {
  244. if( mf )
  245. {
  246. xorBit = 6;
  247. // set register based on cached shortlen
  248. setShortLength( currShortPeriods );
  249. }
  250. else xorBit = 1;
  251. }
  252. void setShortLength( ShortPeriods p )
  253. {
  254. currShortPeriods = p;
  255. if( p == SHORT_31 )
  256. {
  257. setRegister( 0x0737 );
  258. }
  259. else
  260. {
  261. // A little state so we don't always land on the same one
  262. setRegister( starts_for_93s[ curr93key ] );
  263. }
  264. }
  265. void setPeriod( unsigned int c ) // 0 - 15
  266. {
  267. if( c > 15 ) c = 8;
  268. switch( c ) {
  269. case 0:
  270. digWavelength = 4; break;
  271. case 1:
  272. digWavelength = 8; break;
  273. case 2:
  274. digWavelength = 16; break;
  275. case 3:
  276. digWavelength = 32; break;
  277. case 4:
  278. digWavelength = 64; break;
  279. case 5:
  280. digWavelength = 96; break;
  281. case 6:
  282. digWavelength = 128; break;
  283. case 7:
  284. digWavelength = 160; break;
  285. case 8:
  286. digWavelength = 202; break;
  287. case 9:
  288. digWavelength = 254; break;
  289. case 10:
  290. digWavelength = 380; break;
  291. case 11:
  292. digWavelength = 508; break;
  293. case 12:
  294. digWavelength = 762; break;
  295. case 13:
  296. digWavelength = 1016; break;
  297. case 14:
  298. digWavelength = 2034; break;
  299. case 15:
  300. digWavelength = 4068; break;
  301. }
  302. }
  303. void advanceRegister()
  304. {
  305. // Do the LFSR Shift
  306. unsigned short bit = ((shiftRegister >> 0) ^ (shiftRegister >> xorBit)) & 1;
  307. shiftRegister = (shiftRegister >> 1) | (bit << 14); // thanks https://github.com/baconpaul/BaconPlugs/issues/6
  308. }
  309. float step()
  310. {
  311. int ticks = cpu.nextStepCPUTicks();
  312. t -= ticks;
  313. if( t < 0 )
  314. {
  315. t += digWavelength;
  316. advanceRegister();
  317. currentOutput = shiftRegister & 1;
  318. }
  319. return currentOutput * wfMinToMax + wfMin;
  320. }
  321. void setRegister( unsigned short r ) { shiftRegister = r; }
  322. unsigned short getRegister() { return shiftRegister; }
  323. };
  324. #if 0
  325. class LFSRGeneralImpl
  326. {
  327. public:
  328. typedef std::bitset< 24 > bits;
  329. private:
  330. public:
  331. void setActivetBits( size_t aBits ) // < 24 please
  332. {
  333. }
  334. void setTapsAsInt( unsigned int taps ) // so 1 << 16 & 1 << 14 & 1 << 7 type thing
  335. {
  336. }
  337. };
  338. #endif
  339. };