diff options
author | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-15 01:00:20 +0900 |
---|---|---|
committer | Takamichi Horikawa <takamichiho@gmail.com> | 2017-04-15 01:00:20 +0900 |
commit | 680ab52d9e151676b8f90d105b23d2d0d89b0471 (patch) | |
tree | 5a05e82900393d2e1ecdf034cf1735d4ebfaec98 | |
parent | 428126ee4c8802a4b5f9c9ee491d54013857741b (diff) |
add fmdsp fft analyzer
-rw-r--r-- | fft/fft.c | 154 | ||||
-rw-r--r-- | fft/fft.h | 35 | ||||
-rw-r--r-- | fft/fftwindow.h | 1026 | ||||
-rw-r--r-- | fmdriver/fmdriver.h | 8 | ||||
-rw-r--r-- | fmdriver/fmdriver_fmp.c | 10 | ||||
-rw-r--r-- | fmdriver/fmdriver_pmd.c | 13 | ||||
-rw-r--r-- | fmdsp/fmdsp-vramlookup-neon.s | 5 | ||||
-rw-r--r-- | fmdsp/fmdsp.c | 371 | ||||
-rw-r--r-- | fmdsp/fmdsp.h | 14 | ||||
-rw-r--r-- | fmdsp/fmdsp_platform_info.h | 9 | ||||
-rw-r--r-- | fmdsp/fmdsp_platform_unix.c | 44 | ||||
-rw-r--r-- | fmdsp/fmdsp_platform_win.c | 57 | ||||
-rw-r--r-- | fmdsp/fmdsp_sprites.h | 405 | ||||
-rw-r--r-- | fmdsp/font_fmdsp_small_data.h | 15 | ||||
-rw-r--r-- | gtk/Makefile.am | 4 | ||||
-rw-r--r-- | gtk/fmplayer.xpm | 2 | ||||
-rw-r--r-- | gtk/fmplayer32.xpm | 2 | ||||
-rw-r--r-- | gtk/main.c | 23 | ||||
-rw-r--r-- | libopna/opna.c | 2 | ||||
-rw-r--r-- | libopna/opna.h | 1 | ||||
-rw-r--r-- | win32/amd64/Makefile | 1 | ||||
-rw-r--r-- | win32/fmplayer.mak | 4 | ||||
-rw-r--r-- | win32/main.c | 25 | ||||
-rw-r--r-- | win32/wavewrite.c | 6 | ||||
-rw-r--r-- | win32/x86/Makefile | 1 |
25 files changed, 2162 insertions, 75 deletions
diff --git a/fft/fft.c b/fft/fft.c new file mode 100644 index 0000000..69c0971 --- /dev/null +++ b/fft/fft.c @@ -0,0 +1,154 @@ +#include "fft.h" +#include <math.h> +#include <string.h> + +void fft_write(struct fmplayer_fft_data *data, const int16_t *buf, unsigned len) { + if (len > FFTLEN) { + unsigned discard = FFTLEN - len; + buf += discard*2; + len = FFTLEN; + } + unsigned towrite = FFTLEN - data->ind; + if (towrite > len) towrite = len; + for (unsigned i = 0; i < towrite; i++) { + data->buf[data->ind+i] = ((uint32_t)buf[2*i+0] + buf[2*i+1]) / 2; + } + data->ind = (data->ind + towrite) % FFTLEN; + buf += towrite*2; + len -= towrite; + + for (unsigned i = 0; i < len; i++) { + data->buf[i] = ((uint32_t)buf[2*i+0] + buf[2*i+1]) / 2; + } + data->ind = (data->ind + len) % FFTLEN; +} + +static const uint16_t fftfreqtab[FFTDISPLEN+1] = { + 0, + 18, 19, 21, 22, 23, 25, 26, 28, 29, 31, + 33, 35, 37, 39, 42, 44, 47, 50, 53, 56, + 59, 63, 66, 70, 75, 79, 84, 89, 94, 100, + 106, 112, 119, 126, 133, 141, 150, 158, 168, 178, + 189, 200, 212, 224, 238, 252, 267, 283, 300, 317, + 336, 356, 378, 400, 424, 449, 476, 504, 534, 566, + 600, 635, 673, 713, 756, 801, 848, 899, 952, 1009, +}; + +enum { + HFFTLENBIT = 12, + HFFTLEN = 1<<HFFTLENBIT, +}; + +static uint16_t window[FFTLEN]; +static float tritab[FFTLEN + FFTLEN/4]; + +void fft_init_table(void) { + const double pi = acos(0.0) * 2.0; + double alpha = 0.54; + double beta = 1.0 - alpha; + for (unsigned i = 0; i < FFTLEN; i++) { + double v = alpha - beta * cos(2.0*pi*i/(FFTLEN-1)); + window[i] = v * (1<<16); + } + for (unsigned i = 0; i < (FFTLEN + FFTLEN/4); i++) { + tritab[i] = sin(2.0*pi*i/FFTLEN); + } +} + +static float coscalc(unsigned i) { + return tritab[(i & (FFTLEN-1)) + FFTLEN/4]; +} + +static float sincalc(unsigned i) { + return tritab[i & (FFTLEN-1)]; +} + +static float ar(unsigned i) { + return 0.5f*(1.0f-sincalc(i)); +} + +static float ai(unsigned i) { + return -0.5f*coscalc(i); +} + +static float br(unsigned i) { + return 0.5f*(1.0f+sincalc(i)); +} + +static float bi(unsigned i) { + return 0.5f*coscalc(i); +} + +static void fft_real(float *fftbuf) { + unsigned b = 0; + for (unsigned i = 0; i < HFFTLEN; i++) { + unsigned ii = 0; + for (unsigned bit = 0; bit < HFFTLENBIT; bit++) { + ii |= ((i >> bit) & 1u) << (HFFTLENBIT-bit-1); + } + fftbuf[(!b)*FFTLEN+i*2+0] = fftbuf[b*FFTLEN+ii*2+0]; + fftbuf[(!b)*FFTLEN+i*2+1] = fftbuf[b*FFTLEN+ii*2+1]; + } + b = !b; + for (unsigned bit = 0; bit < HFFTLENBIT; bit++) { + for (unsigned i = 0; i < HFFTLEN; i++) { + unsigned ei = i & ~(1u<<bit); + unsigned oi = i | (1u<<bit); + float are = fftbuf[b*FFTLEN+oi*2+0]; + float aim = fftbuf[b*FFTLEN+oi*2+1]; + float bre = coscalc(i<<(HFFTLENBIT-bit)); + float bim = sincalc(i<<(HFFTLENBIT-bit)); + float cre = are*bre - aim*bim; + float cim = are*bim + aim*bre; + fftbuf[(!b)*FFTLEN+i*2+0] = fftbuf[b*FFTLEN+ei*2+0] + cre; + fftbuf[(!b)*FFTLEN+i*2+1] = fftbuf[b*FFTLEN+ei*2+1] + cim; + } + b = !b; + } + for (unsigned i = 0; i < HFFTLEN; i++) { + float xr = fftbuf[b*FFTLEN+i*2+0]; + float rxr = fftbuf[b*FFTLEN+0]; + if (i) rxr = fftbuf[b*FFTLEN+(HFFTLEN-i)*2+0]; + float xi = fftbuf[b*FFTLEN+i*2+1]; + float rxi = fftbuf[b*FFTLEN+1]; + if (i) rxi = fftbuf[b*FFTLEN+(HFFTLEN-i)*2+1]; + fftbuf[(!b)*FFTLEN+i*2+0] = xr * ar(i) - xi * ai(i) + rxr * br(i) + rxi * bi(i); + fftbuf[(!b)*FFTLEN+i*2+1] = xi * ar(i) + xr * ai(i) + rxr * bi(i) - rxi * br(i); + } + if (!b) { + memcpy(fftbuf, fftbuf+FFTLEN, FFTLEN*sizeof(fftbuf[0])); + } +} + +void fft_calc(struct fmplayer_fft_disp_data *ddata, struct fmplayer_fft_input_data *idata) { + for (int i = 0; i < FFTLEN; i++) { + int fi = (i + idata->fdata.ind) % FFTLEN; + idata->work[i] = (((int32_t)idata->fdata.buf[fi]) * window[i]) >> 16; + } + for (int i = 0; i < FFTLEN; i++) { + idata->fwork[i] = ((float)idata->work[i])/32768; + } + fft_real(idata->fwork); + for (int i = 1; i < FFTLEN/2; i++) { + float re = idata->fwork[i*2]; + float im = idata->fwork[i*2+1]; + idata->fwork[i] = sqrtf((re*re) + (im*im)); + } + for (int i = 0; i < FFTLEN/2; i++) { + idata->fwork[i] = idata->fwork[i] / sqrtf(FFTLEN); + } + float dbuf[FFTDISPLEN]; + for (int i = 0; i < FFTDISPLEN; i++) { + dbuf[i] = 0.0f; + for (int j = fftfreqtab[i]; j < fftfreqtab[i+1]; j++) { + dbuf[i] += idata->fwork[j]; + } + dbuf[i] /= fftfreqtab[i+1] - fftfreqtab[i]; + } + for (int i = 0; i < FFTDISPLEN; i++) { + float res = (dbuf[i] > (1.0f / 256)) ? (4.0f*log2f(dbuf[i]) + 32.0f) : 0.0f; + if (res > 31.0f) res = 31.0f; + if (res < 0.0f) res = 0.0f; + ddata->buf[i] = res; + } +} diff --git a/fft/fft.h b/fft/fft.h new file mode 100644 index 0000000..b446739 --- /dev/null +++ b/fft/fft.h @@ -0,0 +1,35 @@ +#ifndef MYON_FMPLAYER_FFT_FFT_H_INCLUDED +#define MYON_FMPLAYER_FFT_FFT_H_INCLUDED + +#include <stdint.h> + +enum { + FFTLEN = 8192, + FFTDISPLEN = 70, +}; + +struct fmplayer_fft_data { + int16_t buf[FFTLEN]; + unsigned ind; +}; + +struct fmplayer_fft_input_data { + struct fmplayer_fft_data fdata; + int16_t work[FFTLEN]; + double dwork[FFTLEN]; + float fwork[FFTLEN*2]; +}; + +struct fmplayer_fft_disp_data { + // 0 - 31 + // 4 per 6db + uint8_t buf[FFTDISPLEN]; +}; + +void fft_init_table(void); + +void fft_write(struct fmplayer_fft_data *data, const int16_t *buf, unsigned len); + +void fft_calc(struct fmplayer_fft_disp_data *ddata, struct fmplayer_fft_input_data *idata); + +#endif // MYON_FMPLAYER_FFT_FFT_H_INCLUDED diff --git a/fft/fftwindow.h b/fft/fftwindow.h new file mode 100644 index 0000000..7dd26dc --- /dev/null +++ b/fft/fftwindow.h @@ -0,0 +1,1026 @@ +static const uint16_t window[8192] = { + 5242, 5242, 5242, 5242, 5243, 5243, 5243, 5243, + 5243, 5243, 5243, 5243, 5244, 5244, 5244, 5244, + 5245, 5245, 5245, 5246, 5246, 5246, 5247, 5247, + 5247, 5248, 5248, 5249, 5249, 5250, 5250, 5251, + 5251, 5252, 5253, 5253, 5254, 5255, 5255, 5256, + 5257, 5257, 5258, 5259, 5260, 5260, 5261, 5262, + 5263, 5264, 5265, 5265, 5266, 5267, 5268, 5269, + 5270, 5271, 5272, 5273, 5274, 5275, 5276, 5278, + 5279, 5280, 5281, 5282, 5283, 5285, 5286, 5287, + 5288, 5290, 5291, 5292, 5294, 5295, 5296, 5298, + 5299, 5301, 5302, 5303, 5305, 5306, 5308, 5309, + 5311, 5313, 5314, 5316, 5317, 5319, 5321, 5322, + 5324, 5326, 5328, 5329, 5331, 5333, 5335, 5336, + 5338, 5340, 5342, 5344, 5346, 5348, 5350, 5352, + 5354, 5356, 5358, 5360, 5362, 5364, 5366, 5368, + 5370, 5372, 5374, 5376, 5379, 5381, 5383, 5385, + 5388, 5390, 5392, 5394, 5397, 5399, 5401, 5404, + 5406, 5409, 5411, 5414, 5416, 5419, 5421, 5424, + 5426, 5429, 5431, 5434, 5436, 5439, 5442, 5444, + 5447, 5450, 5452, 5455, 5458, 5461, 5464, 5466, + 5469, 5472, 5475, 5478, 5481, 5484, 5486, 5489, + 5492, 5495, 5498, 5501, 5504, 5507, 5511, 5514, + 5517, 5520, 5523, 5526, 5529, 5532, 5536, 5539, + 5542, 5545, 5549, 5552, 5555, 5559, 5562, 5565, + 5569, 5572, 5576, 5579, 5582, 5586, 5589, 5593, + 5596, 5600, 5604, 5607, 5611, 5614, 5618, 5622, + 5625, 5629, 5633, 5636, 5640, 5644, 5648, 5651, + 5655, 5659, 5663, 5667, 5671, 5675, 5678, 5682, + 5686, 5690, 5694, 5698, 5702, 5706, 5710, 5714, + 5719, 5723, 5727, 5731, 5735, 5739, 5743, 5748, + 5752, 5756, 5760, 5765, 5769, 5773, 5778, 5782, + 5786, 5791, 5795, 5799, 5804, 5808, 5813, 5817, + 5822, 5826, 5831, 5835, 5840, 5845, 5849, 5854, + 5858, 5863, 5868, 5872, 5877, 5882, 5887, 5891, + 5896, 5901, 5906, 5911, 5915, 5920, 5925, 5930, + 5935, 5940, 5945, 5950, 5955, 5960, 5965, 5970, + 5975, 5980, 5985, 5990, 5995, 6001, 6006, 6011, + 6016, 6021, 6027, 6032, 6037, 6042, 6048, 6053, + 6058, 6064, 6069, 6074, 6080, 6085, 6091, 6096, + 6102, 6107, 6113, 6118, 6124, 6129, 6135, 6140, + 6146, 6152, 6157, 6163, 6169, 6174, 6180, 6186, + 6192, 6197, 6203, 6209, 6215, 6221, 6226, 6232, + 6238, 6244, 6250, 6256, 6262, 6268, 6274, 6280, + 6286, 6292, 6298, 6304, 6310, 6316, 6322, 6329, + 6335, 6341, 6347, 6353, 6359, 6366, 6372, 6378, + 6385, 6391, 6397, 6404, 6410, 6416, 6423, 6429, + 6436, 6442, 6448, 6455, 6461, 6468, 6475, 6481, + 6488, 6494, 6501, 6507, 6514, 6521, 6527, 6534, + 6541, 6548, 6554, 6561, 6568, 6575, 6581, 6588, + 6595, 6602, 6609, 6616, 6623, 6630, 6636, 6643, + 6650, 6657, 6664, 6671, 6678, 6686, 6693, 6700, + 6707, 6714, 6721, 6728, 6735, 6743, 6750, 6757, + 6764, 6772, 6779, 6786, 6793, 6801, 6808, 6815, + 6823, 6830, 6838, 6845, 6853, 6860, 6868, 6875, + 6883, 6890, 6898, 6905, 6913, 6920, 6928, 6936, + 6943, 6951, 6959, 6966, 6974, 6982, 6990, 6997, + 7005, 7013, 7021, 7029, 7036, 7044, 7052, 7060, + 7068, 7076, 7084, 7092, 7100, 7108, 7116, 7124, + 7132, 7140, 7148, 7156, 7164, 7172, 7180, 7189, + 7197, 7205, 7213, 7221, 7230, 7238, 7246, 7255, + 7263, 7271, 7280, 7288, 7296, 7305, 7313, 7322, + 7330, 7338, 7347, 7355, 7364, 7373, 7381, 7390, + 7398, 7407, 7415, 7424, 7433, 7441, 7450, 7459, + 7467, 7476, 7485, 7494, 7502, 7511, 7520, 7529, + 7538, 7547, 7555, 7564, 7573, 7582, 7591, 7600, + 7609, 7618, 7627, 7636, 7645, 7654, 7663, 7672, + 7681, 7691, 7700, 7709, 7718, 7727, 7736, 7746, + 7755, 7764, 7773, 7783, 7792, 7801, 7811, 7820, + 7829, 7839, 7848, 7857, 7867, 7876, 7886, 7895, + 7905, 7914, 7924, 7933, 7943, 7952, 7962, 7972, + 7981, 7991, 8001, 8010, 8020, 8030, 8039, 8049, + 8059, 8069, 8078, 8088, 8098, 8108, 8118, 8128, + 8137, 8147, 8157, 8167, 8177, 8187, 8197, 8207, + 8217, 8227, 8237, 8247, 8257, 8267, 8277, 8288, + 8298, 8308, 8318, 8328, 8338, 8349, 8359, 8369, + 8379, 8390, 8400, 8410, 8421, 8431, 8441, 8452, + 8462, 8472, 8483, 8493, 8504, 8514, 8525, 8535, + 8546, 8556, 8567, 8577, 8588, 8599, 8609, 8620, + 8630, 8641, 8652, 8662, 8673, 8684, 8695, 8705, + 8716, 8727, 8738, 8749, 8759, 8770, 8781, 8792, + 8803, 8814, 8825, 8836, 8847, 8858, 8869, 8880, + 8891, 8902, 8913, 8924, 8935, 8946, 8957, 8968, + 8979, 8990, 9002, 9013, 9024, 9035, 9047, 9058, + 9069, 9080, 9092, 9103, 9114, 9126, 9137, 9148, + 9160, 9171, 9183, 9194, 9205, 9217, 9228, 9240, + 9251, 9263, 9275, 9286, 9298, 9309, 9321, 9332, + 9344, 9356, 9367, 9379, 9391, 9403, 9414, 9426, + 9438, 9450, 9461, 9473, 9485, 9497, 9509, 9521, + 9532, 9544, 9556, 9568, 9580, 9592, 9604, 9616, + 9628, 9640, 9652, 9664, 9676, 9688, 9700, 9712, + 9725, 9737, 9749, 9761, 9773, 9785, 9798, 9810, + 9822, 9834, 9847, 9859, 9871, 9884, 9896, 9908, + 9921, 9933, 9945, 9958, 9970, 9983, 9995, 10008, + 10020, 10033, 10045, 10058, 10070, 10083, 10095, 10108, + 10121, 10133, 10146, 10158, 10171, 10184, 10196, 10209, + 10222, 10235, 10247, 10260, 10273, 10286, 10299, 10311, + 10324, 10337, 10350, 10363, 10376, 10389, 10402, 10414, + 10427, 10440, 10453, 10466, 10479, 10492, 10506, 10519, + 10532, 10545, 10558, 10571, 10584, 10597, 10610, 10624, + 10637, 10650, 10663, 10676, 10690, 10703, 10716, 10730, + 10743, 10756, 10770, 10783, 10796, 10810, 10823, 10836, + 10850, 10863, 10877, 10890, 10904, 10917, 10931, 10944, + 10958, 10971, 10985, 10999, 11012, 11026, 11039, 11053, + 11067, 11080, 11094, 11108, 11121, 11135, 11149, 11163, + 11176, 11190, 11204, 11218, 11232, 11245, 11259, 11273, + 11287, 11301, 11315, 11329, 11343, 11357, 11371, 11385, + 11399, 11413, 11427, 11441, 11455, 11469, 11483, 11497, + 11511, 11525, 11539, 11554, 11568, 11582, 11596, 11610, + 11625, 11639, 11653, 11667, 11682, 11696, 11710, 11724, + 11739, 11753, 11767, 11782, 11796, 11811, 11825, 11840, + 11854, 11868, 11883, 11897, 11912, 11926, 11941, 11955, + 11970, 11985, 11999, 12014, 12028, 12043, 12058, 12072, + 12087, 12102, 12116, 12131, 12146, 12160, 12175, 12190, + 12205, 12220, 12234, 12249, 12264, 12279, 12294, 12309, + 12323, 12338, 12353, 12368, 12383, 12398, 12413, 12428, + 12443, 12458, 12473, 12488, 12503, 12518, 12533, 12548, + 12563, 12579, 12594, 12609, 12624, 12639, 12654, 12669, + 12685, 12700, 12715, 12730, 12746, 12761, 12776, 12792, + 12807, 12822, 12837, 12853, 12868, 12884, 12899, 12914, + 12930, 12945, 12961, 12976, 12992, 13007, 13023, 13038, + 13054, 13069, 13085, 13100, 13116, 13131, 13147, 13163, + 13178, 13194, 13210, 13225, 13241, 13257, 13272, 13288, + 13304, 13320, 13335, 13351, 13367, 13383, 13398, 13414, + 13430, 13446, 13462, 13478, 13494, 13510, 13525, 13541, + 13557, 13573, 13589, 13605, 13621, 13637, 13653, 13669, + 13685, 13701, 13717, 13734, 13750, 13766, 13782, 13798, + 13814, 13830, 13846, 13863, 13879, 13895, 13911, 13927, + 13944, 13960, 13976, 13993, 14009, 14025, 14041, 14058, + 14074, 14091, 14107, 14123, 14140, 14156, 14172, 14189, + 14205, 14222, 14238, 14255, 14271, 14288, 14304, 14321, + 14337, 14354, 14371, 14387, 14404, 14420, 14437, 14454, + 14470, 14487, 14504, 14520, 14537, 14554, 14570, 14587, + 14604, 14621, 14637, 14654, 14671, 14688, 14705, 14721, + 14738, 14755, 14772, 14789, 14806, 14823, 14840, 14856, + 14873, 14890, 14907, 14924, 14941, 14958, 14975, 14992, + 15009, 15026, 15043, 15060, 15078, 15095, 15112, 15129, + 15146, 15163, 15180, 15197, 15215, 15232, 15249, 15266, + 15283, 15301, 15318, 15335, 15353, 15370, 15387, 15404, + 15422, 15439, 15456, 15474, 15491, 15508, 15526, 15543, + 15561, 15578, 15596, 15613, 15630, 15648, 15665, 15683, + 15700, 15718, 15735, 15753, 15771, 15788, 15806, 15823, + 15841, 15858, 15876, 15894, 15911, 15929, 15947, 15964, + 15982, 16000, 16018, 16035, 16053, 16071, 16088, 16106, + 16124, 16142, 16160, 16177, 16195, 16213, 16231, 16249, + 16267, 16285, 16302, 16320, 16338, 16356, 16374, 16392, + 16410, 16428, 16446, 16464, 16482, 16500, 16518, 16536, + 16554, 16572, 16590, 16608, 16626, 16645, 16663, 16681, + 16699, 16717, 16735, 16753, 16772, 16790, 16808, 16826, + 16844, 16863, 16881, 16899, 16917, 16936, 16954, 16972, + 16991, 17009, 17027, 17046, 17064, 17082, 17101, 17119, + 17138, 17156, 17174, 17193, 17211, 17230, 17248, 17267, + 17285, 17304, 17322, 17341, 17359, 17378, 17396, 17415, + 17433, 17452, 17471, 17489, 17508, 17526, 17545, 17564, + 17582, 17601, 17620, 17638, 17657, 17676, 17695, 17713, + 17732, 17751, 17769, 17788, 17807, 17826, 17845, 17863, + 17882, 17901, 17920, 17939, 17958, 17977, 17995, 18014, + 18033, 18052, 18071, 18090, 18109, 18128, 18147, 18166, + 18185, 18204, 18223, 18242, 18261, 18280, 18299, 18318, + 18337, 18356, 18375, 18394, 18413, 18432, 18452, 18471, + 18490, 18509, 18528, 18547, 18567, 18586, 18605, 18624, + 18643, 18663, 18682, 18701, 18720, 18740, 18759, 18778, + 18798, 18817, 18836, 18856, 18875, 18894, 18914, 18933, + 18952, 18972, 18991, 19011, 19030, 19049, 19069, 19088, + 19108, 19127, 19147, 19166, 19186, 19205, 19225, 19244, + 19264, 19283, 19303, 19322, 19342, 19362, 19381, 19401, + 19420, 19440, 19460, 19479, 19499, 19519, 19538, 19558, + 19578, 19597, 19617, 19637, 19656, 19676, 19696, 19716, + 19735, 19755, 19775, 19795, 19814, 19834, 19854, 19874, + 19894, 19914, 19933, 19953, 19973, 19993, 20013, 20033, + 20053, 20073, 20093, 20113, 20132, 20152, 20172, 20192, + 20212, 20232, 20252, 20272, 20292, 20312, 20332, 20352, + 20372, 20392, 20413, 20433, 20453, 20473, 20493, 20513, + 20533, 20553, 20573, 20594, 20614, 20634, 20654, 20674, + 20694, 20715, 20735, 20755, 20775, 20795, 20816, 20836, + 20856, 20876, 20897, 20917, 20937, 20958, 20978, 20998, + 21019, 21039, 21059, 21080, 21100, 21120, 21141, 21161, + 21181, 21202, 21222, 21243, 21263, 21284, 21304, 21324, + 21345, 21365, 21386, 21406, 21427, 21447, 21468, 21488, + 21509, 21529, 21550, 21570, 21591, 21612, 21632, 21653, + 21673, 21694, 21715, 21735, 21756, 21776, 21797, 21818, + 21838, 21859, 21880, 21900, 21921, 21942, 21962, 21983, + 22004, 22025, 22045, 22066, 22087, 22108, 22128, 22149, + 22170, 22191, 22211, 22232, 22253, 22274, 22295, 22316, + 22336, 22357, 22378, 22399, 22420, 22441, 22462, 22482, + 22503, 22524, 22545, 22566, 22587, 22608, 22629, 22650, + 22671, 22692, 22713, 22734, 22755, 22776, 22797, 22818, + 22839, 22860, 22881, 22902, 22923, 22944, 22965, 22986, + 23007, 23028, 23049, 23071, 23092, 23113, 23134, 23155, + 23176, 23197, 23218, 23240, 23261, 23282, 23303, 23324, + 23346, 23367, 23388, 23409, 23430, 23452, 23473, 23494, + 23515, 23537, 23558, 23579, 23600, 23622, 23643, 23664, + 23686, 23707, 23728, 23750, 23771, 23792, 23814, 23835, + 23856, 23878, 23899, 23920, 23942, 23963, 23985, 24006, + 24028, 24049, 24070, 24092, 24113, 24135, 24156, 24178, + 24199, 24221, 24242, 24264, 24285, 24307, 24328, 24350, + 24371, 24393, 24414, 24436, 24457, 24479, 24500, 24522, + 24543, 24565, 24587, 24608, 24630, 24651, 24673, 24695, + 24716, 24738, 24760, 24781, 24803, 24825, 24846, 24868, + 24890, 24911, 24933, 24955, 24976, 24998, 25020, 25041, + 25063, 25085, 25107, 25128, 25150, 25172, 25194, 25215, + 25237, 25259, 25281, 25302, 25324, 25346, 25368, 25390, + 25412, 25433, 25455, 25477, 25499, 25521, 25543, 25564, + 25586, 25608, 25630, 25652, 25674, 25696, 25718, 25739, + 25761, 25783, 25805, 25827, 25849, 25871, 25893, 25915, + 25937, 25959, 25981, 26003, 26025, 26047, 26069, 26091, + 26113, 26135, 26157, 26179, 26201, 26223, 26245, 26267, + 26289, 26311, 26333, 26355, 26377, 26399, 26421, 26443, + 26465, 26488, 26510, 26532, 26554, 26576, 26598, 26620, + 26642, 26664, 26687, 26709, 26731, 26753, 26775, 26797, + 26820, 26842, 26864, 26886, 26908, 26930, 26953, 26975, + 26997, 27019, 27042, 27064, 27086, 27108, 27130, 27153, + 27175, 27197, 27219, 27242, 27264, 27286, 27309, 27331, + 27353, 27375, 27398, 27420, 27442, 27465, 27487, 27509, + 27532, 27554, 27576, 27599, 27621, 27643, 27666, 27688, + 27710, 27733, 27755, 27777, 27800, 27822, 27845, 27867, + 27889, 27912, 27934, 27957, 27979, 28001, 28024, 28046, + 28069, 28091, 28114, 28136, 28158, 28181, 28203, 28226, + 28248, 28271, 28293, 28316, 28338, 28361, 28383, 28406, + 28428, 28451, 28473, 28496, 28518, 28541, 28563, 28586, + 28608, 28631, 28653, 28676, 28698, 28721, 28744, 28766, + 28789, 28811, 28834, 28856, 28879, 28902, 28924, 28947, + 28969, 28992, 29014, 29037, 29060, 29082, 29105, 29128, + 29150, 29173, 29195, 29218, 29241, 29263, 29286, 29309, + 29331, 29354, 29377, 29399, 29422, 29445, 29467, 29490, + 29513, 29535, 29558, 29581, 29603, 29626, 29649, 29671, + 29694, 29717, 29740, 29762, 29785, 29808, 29830, 29853, + 29876, 29899, 29921, 29944, 29967, 29990, 30012, 30035, + 30058, 30081, 30103, 30126, 30149, 30172, 30195, 30217, + 30240, 30263, 30286, 30308, 30331, 30354, 30377, 30400, + 30422, 30445, 30468, 30491, 30514, 30537, 30559, 30582, + 30605, 30628, 30651, 30674, 30696, 30719, 30742, 30765, + 30788, 30811, 30833, 30856, 30879, 30902, 30925, 30948, + 30971, 30994, 31016, 31039, 31062, 31085, 31108, 31131, + 31154, 31177, 31200, 31222, 31245, 31268, 31291, 31314, + 31337, 31360, 31383, 31406, 31429, 31452, 31475, 31497, + 31520, 31543, 31566, 31589, 31612, 31635, 31658, 31681, + 31704, 31727, 31750, 31773, 31796, 31819, 31842, 31865, + 31888, 31911, 31934, 31957, 31980, 32003, 32025, 32048, + 32071, 32094, 32117, 32140, 32163, 32186, 32209, 32232, + 32255, 32278, 32301, 32324, 32347, 32370, 32393, 32416, + 32439, 32462, 32485, 32509, 32532, 32555, 32578, 32601, + 32624, 32647, 32670, 32693, 32716, 32739, 32762, 32785, + 32808, 32831, 32854, 32877, 32900, 32923, 32946, 32969, + 32992, 33015, 33038, 33061, 33084, 33108, 33131, 33154, + 33177, 33200, 33223, 33246, 33269, 33292, 33315, 33338, + 33361, 33384, 33407, 33430, 33454, 33477, 33500, 33523, + 33546, 33569, 33592, 33615, 33638, 33661, 33684, 33707, + 33731, 33754, 33777, 33800, 33823, 33846, 33869, 33892, + 33915, 33938, 33962, 33985, 34008, 34031, 34054, 34077, + 34100, 34123, 34146, 34169, 34193, 34216, 34239, 34262, + 34285, 34308, 34331, 34354, 34377, 34401, 34424, 34447, + 34470, 34493, 34516, 34539, 34562, 34585, 34609, 34632, + 34655, 34678, 34701, 34724, 34747, 34770, 34794, 34817, + 34840, 34863, 34886, 34909, 34932, 34955, 34978, 35002, + 35025, 35048, 35071, 35094, 35117, 35140, 35163, 35187, + 35210, 35233, 35256, 35279, 35302, 35325, 35348, 35372, + 35395, 35418, 35441, 35464, 35487, 35510, 35533, 35557, + 35580, 35603, 35626, 35649, 35672, 35695, 35718, 35742, + 35765, 35788, 35811, 35834, 35857, 35880, 35903, 35927, + 35950, 35973, 35996, 36019, 36042, 36065, 36088, 36112, + 36135, 36158, 36181, 36204, 36227, 36250, 36273, 36296, + 36320, 36343, 36366, 36389, 36412, 36435, 36458, 36481, + 36504, 36528, 36551, 36574, 36597, 36620, 36643, 36666, + 36689, 36712, 36736, 36759, 36782, 36805, 36828, 36851, + 36874, 36897, 36920, 36943, 36966, 36990, 37013, 37036, + 37059, 37082, 37105, 37128, 37151, 37174, 37197, 37220, + 37244, 37267, 37290, 37313, 37336, 37359, 37382, 37405, + 37428, 37451, 37474, 37497, 37520, 37544, 37567, 37590, + 37613, 37636, 37659, 37682, 37705, 37728, 37751, 37774, + 37797, 37820, 37843, 37866, 37889, 37912, 37935, 37958, + 37982, 38005, 38028, 38051, 38074, 38097, 38120, 38143, + 38166, 38189, 38212, 38235, 38258, 38281, 38304, 38327, + 38350, 38373, 38396, 38419, 38442, 38465, 38488, 38511, + 38534, 38557, 38580, 38603, 38626, 38649, 38672, 38695, + 38718, 38741, 38764, 38787, 38810, 38833, 38856, 38879, + 38902, 38925, 38948, 38971, 38994, 39017, 39039, 39062, + 39085, 39108, 39131, 39154, 39177, 39200, 39223, 39246, + 39269, 39292, 39315, 39338, 39361, 39384, 39406, 39429, + 39452, 39475, 39498, 39521, 39544, 39567, 39590, 39613, + 39636, 39658, 39681, 39704, 39727, 39750, 39773, 39796, + 39819, 39841, 39864, 39887, 39910, 39933, 39956, 39979, + 40002, 40024, 40047, 40070, 40093, 40116, 40139, 40161, + 40184, 40207, 40230, 40253, 40276, 40298, 40321, 40344, + 40367, 40390, 40412, 40435, 40458, 40481, 40504, 40526, + 40549, 40572, 40595, 40618, 40640, 40663, 40686, 40709, + 40731, 40754, 40777, 40800, 40822, 40845, 40868, 40891, + 40913, 40936, 40959, 40981, 41004, 41027, 41050, 41072, + 41095, 41118, 41140, 41163, 41186, 41209, 41231, 41254, + 41277, 41299, 41322, 41345, 41367, 41390, 41413, 41435, + 41458, 41481, 41503, 41526, 41549, 41571, 41594, 41616, + 41639, 41662, 41684, 41707, 41730, 41752, 41775, 41797, + 41820, 41842, 41865, 41888, 41910, 41933, 41955, 41978, + 42001, 42023, 42046, 42068, 42091, 42113, 42136, 42158, + 42181, 42203, 42226, 42248, 42271, 42293, 42316, 42339, + 42361, 42384, 42406, 42428, 42451, 42473, 42496, 42518, + 42541, 42563, 42586, 42608, 42631, 42653, 42676, 42698, + 42720, 42743, 42765, 42788, 42810, 42833, 42855, 42877, + 42900, 42922, 42945, 42967, 42989, 43012, 43034, 43056, + 43079, 43101, 43123, 43146, 43168, 43191, 43213, 43235, + 43258, 43280, 43302, 43324, 43347, 43369, 43391, 43414, + 43436, 43458, 43481, 43503, 43525, 43547, 43570, 43592, + 43614, 43636, 43659, 43681, 43703, 43725, 43747, 43770, + 43792, 43814, 43836, 43859, 43881, 43903, 43925, 43947, + 43969, 43992, 44014, 44036, 44058, 44080, 44102, 44124, + 44147, 44169, 44191, 44213, 44235, 44257, 44279, 44301, + 44323, 44346, 44368, 44390, 44412, 44434, 44456, 44478, + 44500, 44522, 44544, 44566, 44588, 44610, 44632, 44654, + 44676, 44698, 44720, 44742, 44764, 44786, 44808, 44830, + 44852, 44874, 44896, 44918, 44940, 44962, 44984, 45006, + 45027, 45049, 45071, 45093, 45115, 45137, 45159, 45181, + 45203, 45224, 45246, 45268, 45290, 45312, 45334, 45355, + 45377, 45399, 45421, 45443, 45465, 45486, 45508, 45530, + 45552, 45573, 45595, 45617, 45639, 45660, 45682, 45704, + 45726, 45747, 45769, 45791, 45812, 45834, 45856, 45878, + 45899, 45921, 45943, 45964, 45986, 46008, 46029, 46051, + 46072, 46094, 46116, 46137, 46159, 46180, 46202, 46224, + 46245, 46267, 46288, 46310, 46331, 46353, 46375, 46396, + 46418, 46439, 46461, 46482, 46504, 46525, 46547, 46568, + 46590, 46611, 46632, 46654, 46675, 46697, 46718, 46740, + 46761, 46783, 46804, 46825, 46847, 46868, 46889, 46911, + 46932, 46954, 46975, 46996, 47018, 47039, 47060, 47082, + 47103, 47124, 47145, 47167, 47188, 47209, 47231, 47252, + 47273, 47294, 47316, 47337, 47358, 47379, 47401, 47422, + 47443, 47464, 47485, 47506, 47528, 47549, 47570, 47591, + 47612, 47633, 47655, 47676, 47697, 47718, 47739, 47760, + 47781, 47802, 47823, 47844, 47865, 47886, 47907, 47929, + 47950, 47971, 47992, 48013, 48034, 48055, 48076, 48097, + 48117, 48138, 48159, 48180, 48201, 48222, 48243, 48264, + 48285, 48306, 48327, 48348, 48368, 48389, 48410, 48431, + 48452, 48473, 48494, 48514, 48535, 48556, 48577, 48598, + 48618, 48639, 48660, 48681, 48701, 48722, 48743, 48764, + 48784, 48805, 48826, 48847, 48867, 48888, 48909, 48929, + 48950, 48971, 48991, 49012, 49032, 49053, 49074, 49094, + 49115, 49135, 49156, 49177, 49197, 49218, 49238, 49259, + 49279, 49300, 49320, 49341, 49361, 49382, 49402, 49423, + 49443, 49464, 49484, 49505, 49525, 49545, 49566, 49586, + 49607, 49627, 49647, 49668, 49688, 49708, 49729, 49749, + 49769, 49790, 49810, 49830, 49851, 49871, 49891, 49912, + 49932, 49952, 49972, 49993, 50013, 50033, 50053, 50073, + 50094, 50114, 50134, 50154, 50174, 50194, 50215, 50235, + 50255, 50275, 50295, 50315, 50335, 50355, 50375, 50395, + 50415, 50436, 50456, 50476, 50496, 50516, 50536, 50556, + 50576, 50596, 50615, 50635, 50655, 50675, 50695, 50715, + 50735, 50755, 50775, 50795, 50815, 50834, 50854, 50874, + 50894, 50914, 50934, 50953, 50973, 50993, 51013, 51033, + 51052, 51072, 51092, 51112, 51131, 51151, 51171, 51190, + 51210, 51230, 51250, 51269, 51289, 51308, 51328, 51348, + 51367, 51387, 51407, 51426, 51446, 51465, 51485, 51504, + 51524, 51543, 51563, 51582, 51602, 51621, 51641, 51660, + 51680, 51699, 51719, 51738, 51758, 51777, 51796, 51816, + 51835, 51855, 51874, 51893, 51913, 51932, 51951, 51971, + 51990, 52009, 52029, 52048, 52067, 52086, 52106, 52125, + 52144, 52163, 52183, 52202, 52221, 52240, 52259, 52278, + 52298, 52317, 52336, 52355, 52374, 52393, 52412, 52431, + 52450, 52469, 52489, 52508, 52527, 52546, 52565, 52584, + 52603, 52622, 52641, 52660, 52678, 52697, 52716, 52735, + 52754, 52773, 52792, 52811, 52830, 52849, 52867, 52886, + 52905, 52924, 52943, 52961, 52980, 52999, 53018, 53037, + 53055, 53074, 53093, 53111, 53130, 53149, 53168, 53186, + 53205, 53224, 53242, 53261, 53279, 53298, 53317, 53335, + 53354, 53372, 53391, 53409, 53428, 53446, 53465, 53483, + 53502, 53520, 53539, 53557, 53576, 53594, 53613, 53631, + 53650, 53668, 53686, 53705, 53723, 53741, 53760, 53778, + 53796, 53815, 53833, 53851, 53870, 53888, 53906, 53924, + 53943, 53961, 53979, 53997, 54015, 54034, 54052, 54070, + 54088, 54106, 54124, 54142, 54160, 54179, 54197, 54215, + 54233, 54251, 54269, 54287, 54305, 54323, 54341, 54359, + 54377, 54395, 54413, 54431, 54449, 54466, 54484, 54502, + 54520, 54538, 54556, 54574, 54592, 54609, 54627, 54645, + 54663, 54681, 54698, 54716, 54734, 54752, 54769, 54787, + 54805, 54822, 54840, 54858, 54875, 54893, 54911, 54928, + 54946, 54963, 54981, 54999, 55016, 55034, 55051, 55069, + 55086, 55104, 55121, 55139, 55156, 55174, 55191, 55208, + 55226, 55243, 55261, 55278, 55295, 55313, 55330, 55347, + 55365, 55382, 55399, 55417, 55434, 55451, 55469, 55486, + 55503, 55520, 55537, 55555, 55572, 55589, 55606, 55623, + 55640, 55658, 55675, 55692, 55709, 55726, 55743, 55760, + 55777, 55794, 55811, 55828, 55845, 55862, 55879, 55896, + 55913, 55930, 55947, 55964, 55981, 55998, 56014, 56031, + 56048, 56065, 56082, 56099, 56115, 56132, 56149, 56166, + 56182, 56199, 56216, 56233, 56249, 56266, 56283, 56299, + 56316, 56333, 56349, 56366, 56382, 56399, 56416, 56432, + 56449, 56465, 56482, 56498, 56515, 56531, 56548, 56564, + 56581, 56597, 56614, 56630, 56646, 56663, 56679, 56696, + 56712, 56728, 56745, 56761, 56777, 56793, 56810, 56826, + 56842, 56859, 56875, 56891, 56907, 56923, 56940, 56956, + 56972, 56988, 57004, 57020, 57036, 57052, 57068, 57085, + 57101, 57117, 57133, 57149, 57165, 57181, 57197, 57213, + 57229, 57244, 57260, 57276, 57292, 57308, 57324, 57340, + 57356, 57371, 57387, 57403, 57419, 57435, 57450, 57466, + 57482, 57498, 57513, 57529, 57545, 57560, 57576, 57592, + 57607, 57623, 57639, 57654, 57670, 57685, 57701, 57716, + 57732, 57748, 57763, 57779, 57794, 57809, 57825, 57840, + 57856, 57871, 57887, 57902, 57917, 57933, 57948, 57963, + 57979, 57994, 58009, 58025, 58040, 58055, 58070, 58086, + 58101, 58116, 58131, 58146, 58162, 58177, 58192, 58207, + 58222, 58237, 58252, 58267, 58282, 58297, 58312, 58327, + 58342, 58357, 58372, 58387, 58402, 58417, 58432, 58447, + 58462, 58477, 58492, 58506, 58521, 58536, 58551, 58566, + 58581, 58595, 58610, 58625, 58640, 58654, 58669, 58684, + 58698, 58713, 58728, 58742, 58757, 58771, 58786, 58801, + 58815, 58830, 58844, 58859, 58873, 58888, 58902, 58917, + 58931, 58946, 58960, 58974, 58989, 59003, 59018, 59032, + 59046, 59061, 59075, 59089, 59103, 59118, 59132, 59146, + 59160, 59175, 59189, 59203, 59217, 59231, 59246, 59260, + 59274, 59288, 59302, 59316, 59330, 59344, 59358, 59372, + 59386, 59400, 59414, 59428, 59442, 59456, 59470, 59484, + 59498, 59512, 59525, 59539, 59553, 59567, 59581, 59595, + 59608, 59622, 59636, 59650, 59663, 59677, 59691, 59704, + 59718, 59732, 59745, 59759, 59773, 59786, 59800, 59813, + 59827, 59840, 59854, 59867, 59881, 59894, 59908, 59921, + 59935, 59948, 59962, 59975, 59988, 60002, 60015, 60028, + 60042, 60055, 60068, 60082, 60095, 60108, 60121, 60134, + 60148, 60161, 60174, 60187, 60200, 60213, 60227, 60240, + 60253, 60266, 60279, 60292, 60305, 60318, 60331, 60344, + 60357, 60370, 60383, 60396, 60409, 60422, 60434, 60447, + 60460, 60473, 60486, 60499, 60511, 60524, 60537, 60550, + 60562, 60575, 60588, 60600, 60613, 60626, 60638, 60651, + 60664, 60676, 60689, 60701, 60714, 60727, 60739, 60752, + 60764, 60777, 60789, 60801, 60814, 60826, 60839, 60851, + 60863, 60876, 60888, 60900, 60913, 60925, 60937, 60950, + 60962, 60974, 60986, 60999, 61011, 61023, 61035, 61047, + 61059, 61071, 61084, 61096, 61108, 61120, 61132, 61144, + 61156, 61168, 61180, 61192, 61204, 61216, 61228, 61240, + 61251, 61263, 61275, 61287, 61299, 61311, 61322, 61334, + 61346, 61358, 61369, 61381, 61393, 61405, 61416, 61428, + 61440, 61451, 61463, 61474, 61486, 61498, 61509, 61521, + 61532, 61544, 61555, 61567, 61578, 61590, 61601, 61612, + 61624, 61635, 61647, 61658, 61669, 61681, 61692, 61703, + 61714, 61726, 61737, 61748, 61759, 61771, 61782, 61793, + 61804, 61815, 61826, 61837, 61849, 61860, 61871, 61882, + 61893, 61904, 61915, 61926, 61937, 61948, 61959, 61970, + 61980, 61991, 62002, 62013, 62024, 62035, 62046, 62056, + 62067, 62078, 62089, 62099, 62110, 62121, 62131, 62142, + 62153, 62163, 62174, 62185, 62195, 62206, 62216, 62227, + 62237, 62248, 62258, 62269, 62279, 62290, 62300, 62311, + 62321, 62331, 62342, 62352, 62362, 62373, 62383, 62393, + 62404, 62414, 62424, 62434, 62445, 62455, 62465, 62475, + 62485, 62495, 62505, 62516, 62526, 62536, 62546, 62556, + 62566, 62576, 62586, 62596, 62606, 62616, 62626, 62635, + 62645, 62655, 62665, 62675, 62685, 62695, 62704, 62714, + 62724, 62734, 62743, 62753, 62763, 62772, 62782, 62792, + 62801, 62811, 62821, 62830, 62840, 62849, 62859, 62868, + 62878, 62887, 62897, 62906, 62916, 62925, 62935, 62944, + 62953, 62963, 62972, 62981, 62991, 63000, 63009, 63018, + 63028, 63037, 63046, 63055, 63064, 63074, 63083, 63092, + 63101, 63110, 63119, 63128, 63137, 63146, 63155, 63164, + 63173, 63182, 63191, 63200, 63209, 63218, 63227, 63236, + 63245, 63253, 63262, 63271, 63280, 63289, 63297, 63306, + 63315, 63324, 63332, 63341, 63350, 63358, 63367, 63375, + 63384, 63393, 63401, 63410, 63418, 63427, 63435, 63444, + 63452, 63461, 63469, 63477, 63486, 63494, 63502, 63511, + 63519, 63527, 63536, 63544, 63552, 63561, 63569, 63577, + 63585, 63593, 63601, 63610, 63618, 63626, 63634, 63642, + 63650, 63658, 63666, 63674, 63682, 63690, 63698, 63706, + 63714, 63722, 63730, 63738, 63745, 63753, 63761, 63769, + 63777, 63784, 63792, 63800, 63808, 63815, 63823, 63831, + 63838, 63846, 63854, 63861, 63869, 63876, 63884, 63892, + 63899, 63907, 63914, 63922, 63929, 63936, 63944, 63951, + 63959, 63966, 63973, 63981, 63988, 63995, 64003, 64010, + 64017, 64024, 64032, 64039, 64046, 64053, 64060, 64068, + 64075, 64082, 64089, 64096, 64103, 64110, 64117, 64124, + 64131, 64138, 64145, 64152, 64159, 64166, 64173, 64179, + 64186, 64193, 64200, 64207, 64213, 64220, 64227, 64234, + 64240, 64247, 64254, 64260, 64267, 64274, 64280, 64287, + 64294, 64300, 64307, 64313, 64320, 64326, 64333, 64339, + 64346, 64352, 64358, 64365, 64371, 64377, 64384, 64390, + 64396, 64403, 64409, 64415, 64422, 64428, 64434, 64440, + 64446, 64452, 64459, 64465, 64471, 64477, 64483, 64489, + 64495, 64501, 64507, 64513, 64519, 64525, 64531, 64537, + 64543, 64549, 64554, 64560, 64566, 64572, 64578, 64583, + 64589, 64595, 64601, 64606, 64612, 64618, 64623, 64629, + 64635, 64640, 64646, 64651, 64657, 64662, 64668, 64673, + 64679, 64684, 64690, 64695, 64701, 64706, 64711, 64717, + 64722, 64728, 64733, 64738, 64743, 64749, 64754, 64759, + 64764, 64770, 64775, 64780, 64785, 64790, 64795, 64800, + 64805, 64810, 64815, 64820, 64825, 64830, 64835, 64840, + 64845, 64850, 64855, 64860, 64865, 64870, 64874, 64879, + 64884, 64889, 64894, 64898, 64903, 64908, 64912, 64917, + 64922, 64926, 64931, 64936, 64940, 64945, 64949, 64954, + 64958, 64963, 64967, 64972, 64976, 64981, 64985, 64989, + 64994, 64998, 65003, 65007, 65011, 65015, 65020, 65024, + 65028, 65032, 65037, 65041, 65045, 65049, 65053, 65057, + 65061, 65065, 65070, 65074, 65078, 65082, 65086, 65090, + 65094, 65097, 65101, 65105, 65109, 65113, 65117, 65121, + 65125, 65128, 65132, 65136, 65140, 65143, 65147, 65151, + 65154, 65158, 65162, 65165, 65169, 65173, 65176, 65180, + 65183, 65187, 65190, 65194, 65197, 65201, 65204, 65207, + 65211, 65214, 65218, 65221, 65224, 65228, 65231, 65234, + 65237, 65241, 65244, 65247, 65250, 65253, 65256, 65260, + 65263, 65266, 65269, 65272, 65275, 65278, 65281, 65284, + 65287, 65290, 65293, 65296, 65299, 65302, 65304, 65307, + 65310, 65313, 65316, 65319, 65321, 65324, 65327, 65329, + 65332, 65335, 65337, 65340, 65343, 65345, 65348, 65350, + 65353, 65356, 65358, 65361, 65363, 65366, 65368, 65370, + 65373, 65375, 65378, 65380, 65382, 65385, 65387, 65389, + 65391, 65394, 65396, 65398, 65400, 65403, 65405, 65407, + 65409, 65411, 65413, 65415, 65417, 65419, 65421, 65423, + 65425, 65427, 65429, 65431, 65433, 65435, 65437, 65439, + 65441, 65442, 65444, 65446, 65448, 65449, 65451, 65453, + 65455, 65456, 65458, 65460, 65461, 65463, 65464, 65466, + 65468, 65469, 65471, 65472, 65474, 65475, 65477, 65478, + 65479, 65481, 65482, 65484, 65485, 65486, 65488, 65489, + 65490, 65491, 65493, 65494, 65495, 65496, 65497, 65499, + 65500, 65501, 65502, 65503, 65504, 65505, 65506, 65507, + 65508, 65509, 65510, 65511, 65512, 65513, 65514, 65515, + 65515, 65516, 65517, 65518, 65519, 65519, 65520, 65521, + 65522, 65522, 65523, 65524, 65524, 65525, 65526, 65526, + 65527, 65527, 65528, 65528, 65529, 65529, 65530, 65530, + 65531, 65531, 65531, 65532, 65532, 65532, 65533, 65533, + 65533, 65534, 65534, 65534, 65534, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65535, 65535, 65535, 65535, 65535, + 65535, 65535, 65535, 65534, 65534, 65534, 65534, 65533, + 65533, 65533, 65532, 65532, 65532, 65531, 65531, 65531, + 65530, 65530, 65529, 65529, 65528, 65528, 65527, 65527, + 65526, 65526, 65525, 65524, 65524, 65523, 65522, 65522, + 65521, 65520, 65519, 65519, 65518, 65517, 65516, 65515, + 65515, 65514, 65513, 65512, 65511, 65510, 65509, 65508, + 65507, 65506, 65505, 65504, 65503, 65502, 65501, 65500, + 65499, 65497, 65496, 65495, 65494, 65493, 65491, 65490, + 65489, 65488, 65486, 65485, 65484, 65482, 65481, 65479, + 65478, 65477, 65475, 65474, 65472, 65471, 65469, 65468, + 65466, 65464, 65463, 65461, 65460, 65458, 65456, 65455, + 65453, 65451, 65449, 65448, 65446, 65444, 65442, 65441, + 65439, 65437, 65435, 65433, 65431, 65429, 65427, 65425, + 65423, 65421, 65419, 65417, 65415, 65413, 65411, 65409, + 65407, 65405, 65403, 65400, 65398, 65396, 65394, 65391, + 65389, 65387, 65385, 65382, 65380, 65378, 65375, 65373, + 65370, 65368, 65366, 65363, 65361, 65358, 65356, 65353, + 65350, 65348, 65345, 65343, 65340, 65337, 65335, 65332, + 65329, 65327, 65324, 65321, 65319, 65316, 65313, 65310, + 65307, 65304, 65302, 65299, 65296, 65293, 65290, 65287, + 65284, 65281, 65278, 65275, 65272, 65269, 65266, 65263, + 65260, 65256, 65253, 65250, 65247, 65244, 65241, 65237, + 65234, 65231, 65228, 65224, 65221, 65218, 65214, 65211, + 65207, 65204, 65201, 65197, 65194, 65190, 65187, 65183, + 65180, 65176, 65173, 65169, 65165, 65162, 65158, 65154, + 65151, 65147, 65143, 65140, 65136, 65132, 65128, 65125, + 65121, 65117, 65113, 65109, 65105, 65101, 65097, 65094, + 65090, 65086, 65082, 65078, 65074, 65070, 65065, 65061, + 65057, 65053, 65049, 65045, 65041, 65037, 65032, 65028, + 65024, 65020, 65015, 65011, 65007, 65003, 64998, 64994, + 64989, 64985, 64981, 64976, 64972, 64967, 64963, 64958, + 64954, 64949, 64945, 64940, 64936, 64931, 64926, 64922, + 64917, 64912, 64908, 64903, 64898, 64894, 64889, 64884, + 64879, 64874, 64870, 64865, 64860, 64855, 64850, 64845, + 64840, 64835, 64830, 64825, 64820, 64815, 64810, 64805, + 64800, 64795, 64790, 64785, 64780, 64775, 64770, 64764, + 64759, 64754, 64749, 64743, 64738, 64733, 64728, 64722, + 64717, 64711, 64706, 64701, 64695, 64690, 64684, 64679, + 64673, 64668, 64662, 64657, 64651, 64646, 64640, 64635, + 64629, 64623, 64618, 64612, 64606, 64601, 64595, 64589, + 64583, 64578, 64572, 64566, 64560, 64554, 64549, 64543, + 64537, 64531, 64525, 64519, 64513, 64507, 64501, 64495, + 64489, 64483, 64477, 64471, 64465, 64459, 64452, 64446, + 64440, 64434, 64428, 64422, 64415, 64409, 64403, 64396, + 64390, 64384, 64377, 64371, 64365, 64358, 64352, 64346, + 64339, 64333, 64326, 64320, 64313, 64307, 64300, 64294, + 64287, 64280, 64274, 64267, 64260, 64254, 64247, 64240, + 64234, 64227, 64220, 64213, 64207, 64200, 64193, 64186, + 64179, 64173, 64166, 64159, 64152, 64145, 64138, 64131, + 64124, 64117, 64110, 64103, 64096, 64089, 64082, 64075, + 64068, 64060, 64053, 64046, 64039, 64032, 64024, 64017, + 64010, 64003, 63995, 63988, 63981, 63973, 63966, 63959, + 63951, 63944, 63936, 63929, 63922, 63914, 63907, 63899, + 63892, 63884, 63876, 63869, 63861, 63854, 63846, 63838, + 63831, 63823, 63815, 63808, 63800, 63792, 63784, 63777, + 63769, 63761, 63753, 63745, 63738, 63730, 63722, 63714, + 63706, 63698, 63690, 63682, 63674, 63666, 63658, 63650, + 63642, 63634, 63626, 63618, 63610, 63601, 63593, 63585, + 63577, 63569, 63561, 63552, 63544, 63536, 63527, 63519, + 63511, 63502, 63494, 63486, 63477, 63469, 63461, 63452, + 63444, 63435, 63427, 63418, 63410, 63401, 63393, 63384, + 63375, 63367, 63358, 63350, 63341, 63332, 63324, 63315, + 63306, 63297, 63289, 63280, 63271, 63262, 63253, 63245, + 63236, 63227, 63218, 63209, 63200, 63191, 63182, 63173, + 63164, 63155, 63146, 63137, 63128, 63119, 63110, 63101, + 63092, 63083, 63074, 63064, 63055, 63046, 63037, 63028, + 63018, 63009, 63000, 62991, 62981, 62972, 62963, 62953, + 62944, 62935, 62925, 62916, 62906, 62897, 62887, 62878, + 62868, 62859, 62849, 62840, 62830, 62821, 62811, 62801, + 62792, 62782, 62772, 62763, 62753, 62743, 62734, 62724, + 62714, 62704, 62695, 62685, 62675, 62665, 62655, 62645, + 62635, 62626, 62616, 62606, 62596, 62586, 62576, 62566, + 62556, 62546, 62536, 62526, 62516, 62505, 62495, 62485, + 62475, 62465, 62455, 62445, 62434, 62424, 62414, 62404, + 62393, 62383, 62373, 62362, 62352, 62342, 62331, 62321, + 62311, 62300, 62290, 62279, 62269, 62258, 62248, 62237, + 62227, 62216, 62206, 62195, 62185, 62174, 62163, 62153, + 62142, 62131, 62121, 62110, 62099, 62089, 62078, 62067, + 62056, 62046, 62035, 62024, 62013, 62002, 61991, 61980, + 61970, 61959, 61948, 61937, 61926, 61915, 61904, 61893, + 61882, 61871, 61860, 61849, 61837, 61826, 61815, 61804, + 61793, 61782, 61771, 61759, 61748, 61737, 61726, 61714, + 61703, 61692, 61681, 61669, 61658, 61647, 61635, 61624, + 61612, 61601, 61590, 61578, 61567, 61555, 61544, 61532, + 61521, 61509, 61498, 61486, 61474, 61463, 61451, 61440, + 61428, 61416, 61405, 61393, 61381, 61369, 61358, 61346, + 61334, 61322, 61311, 61299, 61287, 61275, 61263, 61251, + 61240, 61228, 61216, 61204, 61192, 61180, 61168, 61156, + 61144, 61132, 61120, 61108, 61096, 61084, 61071, 61059, + 61047, 61035, 61023, 61011, 60999, 60986, 60974, 60962, + 60950, 60937, 60925, 60913, 60900, 60888, 60876, 60863, + 60851, 60839, 60826, 60814, 60801, 60789, 60777, 60764, + 60752, 60739, 60727, 60714, 60701, 60689, 60676, 60664, + 60651, 60638, 60626, 60613, 60600, 60588, 60575, 60562, + 60550, 60537, 60524, 60511, 60499, 60486, 60473, 60460, + 60447, 60434, 60422, 60409, 60396, 60383, 60370, 60357, + 60344, 60331, 60318, 60305, 60292, 60279, 60266, 60253, + 60240, 60227, 60213, 60200, 60187, 60174, 60161, 60148, + 60134, 60121, 60108, 60095, 60082, 60068, 60055, 60042, + 60028, 60015, 60002, 59988, 59975, 59962, 59948, 59935, + 59921, 59908, 59894, 59881, 59867, 59854, 59840, 59827, + 59813, 59800, 59786, 59773, 59759, 59745, 59732, 59718, + 59704, 59691, 59677, 59663, 59650, 59636, 59622, 59608, + 59595, 59581, 59567, 59553, 59539, 59525, 59512, 59498, + 59484, 59470, 59456, 59442, 59428, 59414, 59400, 59386, + 59372, 59358, 59344, 59330, 59316, 59302, 59288, 59274, + 59260, 59246, 59231, 59217, 59203, 59189, 59175, 59160, + 59146, 59132, 59118, 59103, 59089, 59075, 59061, 59046, + 59032, 59018, 59003, 58989, 58974, 58960, 58946, 58931, + 58917, 58902, 58888, 58873, 58859, 58844, 58830, 58815, + 58801, 58786, 58771, 58757, 58742, 58728, 58713, 58698, + 58684, 58669, 58654, 58640, 58625, 58610, 58595, 58581, + 58566, 58551, 58536, 58521, 58506, 58492, 58477, 58462, + 58447, 58432, 58417, 58402, 58387, 58372, 58357, 58342, + 58327, 58312, 58297, 58282, 58267, 58252, 58237, 58222, + 58207, 58192, 58177, 58162, 58146, 58131, 58116, 58101, + 58086, 58070, 58055, 58040, 58025, 58009, 57994, 57979, + 57963, 57948, 57933, 57917, 57902, 57887, 57871, 57856, + 57840, 57825, 57809, 57794, 57779, 57763, 57748, 57732, + 57716, 57701, 57685, 57670, 57654, 57639, 57623, 57607, + 57592, 57576, 57560, 57545, 57529, 57513, 57498, 57482, + 57466, 57450, 57435, 57419, 57403, 57387, 57371, 57356, + 57340, 57324, 57308, 57292, 57276, 57260, 57244, 57229, + 57213, 57197, 57181, 57165, 57149, 57133, 57117, 57101, + 57085, 57068, 57052, 57036, 57020, 57004, 56988, 56972, + 56956, 56940, 56923, 56907, 56891, 56875, 56859, 56842, + 56826, 56810, 56793, 56777, 56761, 56745, 56728, 56712, + 56696, 56679, 56663, 56646, 56630, 56614, 56597, 56581, + 56564, 56548, 56531, 56515, 56498, 56482, 56465, 56449, + 56432, 56416, 56399, 56382, 56366, 56349, 56333, 56316, + 56299, 56283, 56266, 56249, 56233, 56216, 56199, 56182, + 56166, 56149, 56132, 56115, 56099, 56082, 56065, 56048, + 56031, 56014, 55998, 55981, 55964, 55947, 55930, 55913, + 55896, 55879, 55862, 55845, 55828, 55811, 55794, 55777, + 55760, 55743, 55726, 55709, 55692, 55675, 55658, 55640, + 55623, 55606, 55589, 55572, 55555, 55537, 55520, 55503, + 55486, 55469, 55451, 55434, 55417, 55399, 55382, 55365, + 55347, 55330, 55313, 55295, 55278, 55261, 55243, 55226, + 55208, 55191, 55174, 55156, 55139, 55121, 55104, 55086, + 55069, 55051, 55034, 55016, 54999, 54981, 54963, 54946, + 54928, 54911, 54893, 54875, 54858, 54840, 54822, 54805, + 54787, 54769, 54752, 54734, 54716, 54698, 54681, 54663, + 54645, 54627, 54609, 54592, 54574, 54556, 54538, 54520, + 54502, 54484, 54466, 54449, 54431, 54413, 54395, 54377, + 54359, 54341, 54323, 54305, 54287, 54269, 54251, 54233, + 54215, 54197, 54179, 54160, 54142, 54124, 54106, 54088, + 54070, 54052, 54034, 54015, 53997, 53979, 53961, 53943, + 53924, 53906, 53888, 53870, 53851, 53833, 53815, 53796, + 53778, 53760, 53741, 53723, 53705, 53686, 53668, 53650, + 53631, 53613, 53594, 53576, 53557, 53539, 53520, 53502, + 53483, 53465, 53446, 53428, 53409, 53391, 53372, 53354, + 53335, 53317, 53298, 53279, 53261, 53242, 53224, 53205, + 53186, 53168, 53149, 53130, 53111, 53093, 53074, 53055, + 53037, 53018, 52999, 52980, 52961, 52943, 52924, 52905, + 52886, 52867, 52849, 52830, 52811, 52792, 52773, 52754, + 52735, 52716, 52697, 52678, 52660, 52641, 52622, 52603, + 52584, 52565, 52546, 52527, 52508, 52489, 52469, 52450, + 52431, 52412, 52393, 52374, 52355, 52336, 52317, 52298, + 52278, 52259, 52240, 52221, 52202, 52183, 52163, 52144, + 52125, 52106, 52086, 52067, 52048, 52029, 52009, 51990, + 51971, 51951, 51932, 51913, 51893, 51874, 51855, 51835, + 51816, 51796, 51777, 51758, 51738, 51719, 51699, 51680, + 51660, 51641, 51621, 51602, 51582, 51563, 51543, 51524, + 51504, 51485, 51465, 51446, 51426, 51407, 51387, 51367, + 51348, 51328, 51308, 51289, 51269, 51250, 51230, 51210, + 51190, 51171, 51151, 51131, 51112, 51092, 51072, 51052, + 51033, 51013, 50993, 50973, 50953, 50934, 50914, 50894, + 50874, 50854, 50834, 50815, 50795, 50775, 50755, 50735, + 50715, 50695, 50675, 50655, 50635, 50615, 50596, 50576, + 50556, 50536, 50516, 50496, 50476, 50456, 50436, 50415, + 50395, 50375, 50355, 50335, 50315, 50295, 50275, 50255, + 50235, 50215, 50194, 50174, 50154, 50134, 50114, 50094, + 50073, 50053, 50033, 50013, 49993, 49972, 49952, 49932, + 49912, 49891, 49871, 49851, 49830, 49810, 49790, 49769, + 49749, 49729, 49708, 49688, 49668, 49647, 49627, 49607, + 49586, 49566, 49545, 49525, 49505, 49484, 49464, 49443, + 49423, 49402, 49382, 49361, 49341, 49320, 49300, 49279, + 49259, 49238, 49218, 49197, 49177, 49156, 49135, 49115, + 49094, 49074, 49053, 49032, 49012, 48991, 48971, 48950, + 48929, 48909, 48888, 48867, 48847, 48826, 48805, 48784, + 48764, 48743, 48722, 48701, 48681, 48660, 48639, 48618, + 48598, 48577, 48556, 48535, 48514, 48494, 48473, 48452, + 48431, 48410, 48389, 48368, 48348, 48327, 48306, 48285, + 48264, 48243, 48222, 48201, 48180, 48159, 48138, 48117, + 48097, 48076, 48055, 48034, 48013, 47992, 47971, 47950, + 47929, 47907, 47886, 47865, 47844, 47823, 47802, 47781, + 47760, 47739, 47718, 47697, 47676, 47655, 47633, 47612, + 47591, 47570, 47549, 47528, 47506, 47485, 47464, 47443, + 47422, 47401, 47379, 47358, 47337, 47316, 47294, 47273, + 47252, 47231, 47209, 47188, 47167, 47145, 47124, 47103, + 47082, 47060, 47039, 47018, 46996, 46975, 46954, 46932, + 46911, 46889, 46868, 46847, 46825, 46804, 46783, 46761, + 46740, 46718, 46697, 46675, 46654, 46632, 46611, 46590, + 46568, 46547, 46525, 46504, 46482, 46461, 46439, 46418, + 46396, 46375, 46353, 46331, 46310, 46288, 46267, 46245, + 46224, 46202, 46180, 46159, 46137, 46116, 46094, 46072, + 46051, 46029, 46008, 45986, 45964, 45943, 45921, 45899, + 45878, 45856, 45834, 45812, 45791, 45769, 45747, 45726, + 45704, 45682, 45660, 45639, 45617, 45595, 45573, 45552, + 45530, 45508, 45486, 45465, 45443, 45421, 45399, 45377, + 45355, 45334, 45312, 45290, 45268, 45246, 45224, 45203, + 45181, 45159, 45137, 45115, 45093, 45071, 45049, 45027, + 45006, 44984, 44962, 44940, 44918, 44896, 44874, 44852, + 44830, 44808, 44786, 44764, 44742, 44720, 44698, 44676, + 44654, 44632, 44610, 44588, 44566, 44544, 44522, 44500, + 44478, 44456, 44434, 44412, 44390, 44368, 44346, 44323, + 44301, 44279, 44257, 44235, 44213, 44191, 44169, 44147, + 44124, 44102, 44080, 44058, 44036, 44014, 43992, 43969, + 43947, 43925, 43903, 43881, 43859, 43836, 43814, 43792, + 43770, 43747, 43725, 43703, 43681, 43659, 43636, 43614, + 43592, 43570, 43547, 43525, 43503, 43481, 43458, 43436, + 43414, 43391, 43369, 43347, 43324, 43302, 43280, 43258, + 43235, 43213, 43191, 43168, 43146, 43123, 43101, 43079, + 43056, 43034, 43012, 42989, 42967, 42945, 42922, 42900, + 42877, 42855, 42833, 42810, 42788, 42765, 42743, 42720, + 42698, 42676, 42653, 42631, 42608, 42586, 42563, 42541, + 42518, 42496, 42473, 42451, 42428, 42406, 42384, 42361, + 42339, 42316, 42293, 42271, 42248, 42226, 42203, 42181, + 42158, 42136, 42113, 42091, 42068, 42046, 42023, 42001, + 41978, 41955, 41933, 41910, 41888, 41865, 41842, 41820, + 41797, 41775, 41752, 41730, 41707, 41684, 41662, 41639, + 41616, 41594, 41571, 41549, 41526, 41503, 41481, 41458, + 41435, 41413, 41390, 41367, 41345, 41322, 41299, 41277, + 41254, 41231, 41209, 41186, 41163, 41140, 41118, 41095, + 41072, 41050, 41027, 41004, 40981, 40959, 40936, 40913, + 40891, 40868, 40845, 40822, 40800, 40777, 40754, 40731, + 40709, 40686, 40663, 40640, 40618, 40595, 40572, 40549, + 40526, 40504, 40481, 40458, 40435, 40412, 40390, 40367, + 40344, 40321, 40298, 40276, 40253, 40230, 40207, 40184, + 40161, 40139, 40116, 40093, 40070, 40047, 40024, 40002, + 39979, 39956, 39933, 39910, 39887, 39864, 39841, 39819, + 39796, 39773, 39750, 39727, 39704, 39681, 39658, 39636, + 39613, 39590, 39567, 39544, 39521, 39498, 39475, 39452, + 39429, 39406, 39384, 39361, 39338, 39315, 39292, 39269, + 39246, 39223, 39200, 39177, 39154, 39131, 39108, 39085, + 39062, 39039, 39017, 38994, 38971, 38948, 38925, 38902, + 38879, 38856, 38833, 38810, 38787, 38764, 38741, 38718, + 38695, 38672, 38649, 38626, 38603, 38580, 38557, 38534, + 38511, 38488, 38465, 38442, 38419, 38396, 38373, 38350, + 38327, 38304, 38281, 38258, 38235, 38212, 38189, 38166, + 38143, 38120, 38097, 38074, 38051, 38028, 38005, 37982, + 37958, 37935, 37912, 37889, 37866, 37843, 37820, 37797, + 37774, 37751, 37728, 37705, 37682, 37659, 37636, 37613, + 37590, 37567, 37544, 37520, 37497, 37474, 37451, 37428, + 37405, 37382, 37359, 37336, 37313, 37290, 37267, 37244, + 37220, 37197, 37174, 37151, 37128, 37105, 37082, 37059, + 37036, 37013, 36990, 36966, 36943, 36920, 36897, 36874, + 36851, 36828, 36805, 36782, 36759, 36736, 36712, 36689, + 36666, 36643, 36620, 36597, 36574, 36551, 36528, 36504, + 36481, 36458, 36435, 36412, 36389, 36366, 36343, 36320, + 36296, 36273, 36250, 36227, 36204, 36181, 36158, 36135, + 36112, 36088, 36065, 36042, 36019, 35996, 35973, 35950, + 35927, 35903, 35880, 35857, 35834, 35811, 35788, 35765, + 35742, 35718, 35695, 35672, 35649, 35626, 35603, 35580, + 35557, 35533, 35510, 35487, 35464, 35441, 35418, 35395, + 35372, 35348, 35325, 35302, 35279, 35256, 35233, 35210, + 35187, 35163, 35140, 35117, 35094, 35071, 35048, 35025, + 35002, 34978, 34955, 34932, 34909, 34886, 34863, 34840, + 34817, 34794, 34770, 34747, 34724, 34701, 34678, 34655, + 34632, 34609, 34585, 34562, 34539, 34516, 34493, 34470, + 34447, 34424, 34401, 34377, 34354, 34331, 34308, 34285, + 34262, 34239, 34216, 34193, 34169, 34146, 34123, 34100, + 34077, 34054, 34031, 34008, 33985, 33962, 33938, 33915, + 33892, 33869, 33846, 33823, 33800, 33777, 33754, 33731, + 33707, 33684, 33661, 33638, 33615, 33592, 33569, 33546, + 33523, 33500, 33477, 33454, 33430, 33407, 33384, 33361, + 33338, 33315, 33292, 33269, 33246, 33223, 33200, 33177, + 33154, 33131, 33108, 33084, 33061, 33038, 33015, 32992, + 32969, 32946, 32923, 32900, 32877, 32854, 32831, 32808, + 32785, 32762, 32739, 32716, 32693, 32670, 32647, 32624, + 32601, 32578, 32555, 32532, 32509, 32485, 32462, 32439, + 32416, 32393, 32370, 32347, 32324, 32301, 32278, 32255, + 32232, 32209, 32186, 32163, 32140, 32117, 32094, 32071, + 32048, 32025, 32003, 31980, 31957, 31934, 31911, 31888, + 31865, 31842, 31819, 31796, 31773, 31750, 31727, 31704, + 31681, 31658, 31635, 31612, 31589, 31566, 31543, 31520, + 31497, 31475, 31452, 31429, 31406, 31383, 31360, 31337, + 31314, 31291, 31268, 31245, 31222, 31200, 31177, 31154, + 31131, 31108, 31085, 31062, 31039, 31016, 30994, 30971, + 30948, 30925, 30902, 30879, 30856, 30833, 30811, 30788, + 30765, 30742, 30719, 30696, 30674, 30651, 30628, 30605, + 30582, 30559, 30537, 30514, 30491, 30468, 30445, 30422, + 30400, 30377, 30354, 30331, 30308, 30286, 30263, 30240, + 30217, 30195, 30172, 30149, 30126, 30103, 30081, 30058, + 30035, 30012, 29990, 29967, 29944, 29921, 29899, 29876, + 29853, 29830, 29808, 29785, 29762, 29740, 29717, 29694, + 29671, 29649, 29626, 29603, 29581, 29558, 29535, 29513, + 29490, 29467, 29445, 29422, 29399, 29377, 29354, 29331, + 29309, 29286, 29263, 29241, 29218, 29195, 29173, 29150, + 29128, 29105, 29082, 29060, 29037, 29014, 28992, 28969, + 28947, 28924, 28902, 28879, 28856, 28834, 28811, 28789, + 28766, 28744, 28721, 28698, 28676, 28653, 28631, 28608, + 28586, 28563, 28541, 28518, 28496, 28473, 28451, 28428, + 28406, 28383, 28361, 28338, 28316, 28293, 28271, 28248, + 28226, 28203, 28181, 28158, 28136, 28114, 28091, 28069, + 28046, 28024, 28001, 27979, 27957, 27934, 27912, 27889, + 27867, 27845, 27822, 27800, 27777, 27755, 27733, 27710, + 27688, 27666, 27643, 27621, 27599, 27576, 27554, 27532, + 27509, 27487, 27465, 27442, 27420, 27398, 27375, 27353, + 27331, 27309, 27286, 27264, 27242, 27219, 27197, 27175, + 27153, 27130, 27108, 27086, 27064, 27042, 27019, 26997, + 26975, 26953, 26930, 26908, 26886, 26864, 26842, 26820, + 26797, 26775, 26753, 26731, 26709, 26687, 26664, 26642, + 26620, 26598, 26576, 26554, 26532, 26510, 26488, 26465, + 26443, 26421, 26399, 26377, 26355, 26333, 26311, 26289, + 26267, 26245, 26223, 26201, 26179, 26157, 26135, 26113, + 26091, 26069, 26047, 26025, 26003, 25981, 25959, 25937, + 25915, 25893, 25871, 25849, 25827, 25805, 25783, 25761, + 25739, 25718, 25696, 25674, 25652, 25630, 25608, 25586, + 25564, 25543, 25521, 25499, 25477, 25455, 25433, 25412, + 25390, 25368, 25346, 25324, 25302, 25281, 25259, 25237, + 25215, 25194, 25172, 25150, 25128, 25107, 25085, 25063, + 25041, 25020, 24998, 24976, 24955, 24933, 24911, 24890, + 24868, 24846, 24825, 24803, 24781, 24760, 24738, 24716, + 24695, 24673, 24651, 24630, 24608, 24587, 24565, 24543, + 24522, 24500, 24479, 24457, 24436, 24414, 24393, 24371, + 24350, 24328, 24307, 24285, 24264, 24242, 24221, 24199, + 24178, 24156, 24135, 24113, 24092, 24070, 24049, 24028, + 24006, 23985, 23963, 23942, 23920, 23899, 23878, 23856, + 23835, 23814, 23792, 23771, 23750, 23728, 23707, 23686, + 23664, 23643, 23622, 23600, 23579, 23558, 23537, 23515, + 23494, 23473, 23452, 23430, 23409, 23388, 23367, 23346, + 23324, 23303, 23282, 23261, 23240, 23218, 23197, 23176, + 23155, 23134, 23113, 23092, 23071, 23049, 23028, 23007, + 22986, 22965, 22944, 22923, 22902, 22881, 22860, 22839, + 22818, 22797, 22776, 22755, 22734, 22713, 22692, 22671, + 22650, 22629, 22608, 22587, 22566, 22545, 22524, 22503, + 22482, 22462, 22441, 22420, 22399, 22378, 22357, 22336, + 22316, 22295, 22274, 22253, 22232, 22211, 22191, 22170, + 22149, 22128, 22108, 22087, 22066, 22045, 22025, 22004, + 21983, 21962, 21942, 21921, 21900, 21880, 21859, 21838, + 21818, 21797, 21776, 21756, 21735, 21715, 21694, 21673, + 21653, 21632, 21612, 21591, 21570, 21550, 21529, 21509, + 21488, 21468, 21447, 21427, 21406, 21386, 21365, 21345, + 21324, 21304, 21284, 21263, 21243, 21222, 21202, 21181, + 21161, 21141, 21120, 21100, 21080, 21059, 21039, 21019, + 20998, 20978, 20958, 20937, 20917, 20897, 20876, 20856, + 20836, 20816, 20795, 20775, 20755, 20735, 20715, 20694, + 20674, 20654, 20634, 20614, 20594, 20573, 20553, 20533, + 20513, 20493, 20473, 20453, 20433, 20413, 20392, 20372, + 20352, 20332, 20312, 20292, 20272, 20252, 20232, 20212, + 20192, 20172, 20152, 20132, 20113, 20093, 20073, 20053, + 20033, 20013, 19993, 19973, 19953, 19933, 19914, 19894, + 19874, 19854, 19834, 19814, 19795, 19775, 19755, 19735, + 19716, 19696, 19676, 19656, 19637, 19617, 19597, 19578, + 19558, 19538, 19519, 19499, 19479, 19460, 19440, 19420, + 19401, 19381, 19362, 19342, 19322, 19303, 19283, 19264, + 19244, 19225, 19205, 19186, 19166, 19147, 19127, 19108, + 19088, 19069, 19049, 19030, 19011, 18991, 18972, 18952, + 18933, 18914, 18894, 18875, 18856, 18836, 18817, 18798, + 18778, 18759, 18740, 18720, 18701, 18682, 18663, 18643, + 18624, 18605, 18586, 18567, 18547, 18528, 18509, 18490, + 18471, 18452, 18432, 18413, 18394, 18375, 18356, 18337, + 18318, 18299, 18280, 18261, 18242, 18223, 18204, 18185, + 18166, 18147, 18128, 18109, 18090, 18071, 18052, 18033, + 18014, 17995, 17977, 17958, 17939, 17920, 17901, 17882, + 17863, 17845, 17826, 17807, 17788, 17769, 17751, 17732, + 17713, 17695, 17676, 17657, 17638, 17620, 17601, 17582, + 17564, 17545, 17526, 17508, 17489, 17471, 17452, 17433, + 17415, 17396, 17378, 17359, 17341, 17322, 17304, 17285, + 17267, 17248, 17230, 17211, 17193, 17174, 17156, 17138, + 17119, 17101, 17082, 17064, 17046, 17027, 17009, 16991, + 16972, 16954, 16936, 16917, 16899, 16881, 16863, 16844, + 16826, 16808, 16790, 16772, 16753, 16735, 16717, 16699, + 16681, 16663, 16645, 16626, 16608, 16590, 16572, 16554, + 16536, 16518, 16500, 16482, 16464, 16446, 16428, 16410, + 16392, 16374, 16356, 16338, 16320, 16302, 16285, 16267, + 16249, 16231, 16213, 16195, 16177, 16160, 16142, 16124, + 16106, 16088, 16071, 16053, 16035, 16018, 16000, 15982, + 15964, 15947, 15929, 15911, 15894, 15876, 15858, 15841, + 15823, 15806, 15788, 15771, 15753, 15735, 15718, 15700, + 15683, 15665, 15648, 15630, 15613, 15596, 15578, 15561, + 15543, 15526, 15508, 15491, 15474, 15456, 15439, 15422, + 15404, 15387, 15370, 15353, 15335, 15318, 15301, 15283, + 15266, 15249, 15232, 15215, 15197, 15180, 15163, 15146, + 15129, 15112, 15095, 15078, 15060, 15043, 15026, 15009, + 14992, 14975, 14958, 14941, 14924, 14907, 14890, 14873, + 14856, 14840, 14823, 14806, 14789, 14772, 14755, 14738, + 14721, 14705, 14688, 14671, 14654, 14637, 14621, 14604, + 14587, 14570, 14554, 14537, 14520, 14504, 14487, 14470, + 14454, 14437, 14420, 14404, 14387, 14371, 14354, 14337, + 14321, 14304, 14288, 14271, 14255, 14238, 14222, 14205, + 14189, 14172, 14156, 14140, 14123, 14107, 14091, 14074, + 14058, 14041, 14025, 14009, 13993, 13976, 13960, 13944, + 13927, 13911, 13895, 13879, 13863, 13846, 13830, 13814, + 13798, 13782, 13766, 13750, 13734, 13717, 13701, 13685, + 13669, 13653, 13637, 13621, 13605, 13589, 13573, 13557, + 13541, 13525, 13510, 13494, 13478, 13462, 13446, 13430, + 13414, 13398, 13383, 13367, 13351, 13335, 13320, 13304, + 13288, 13272, 13257, 13241, 13225, 13210, 13194, 13178, + 13163, 13147, 13131, 13116, 13100, 13085, 13069, 13054, + 13038, 13023, 13007, 12992, 12976, 12961, 12945, 12930, + 12914, 12899, 12884, 12868, 12853, 12837, 12822, 12807, + 12792, 12776, 12761, 12746, 12730, 12715, 12700, 12685, + 12669, 12654, 12639, 12624, 12609, 12594, 12579, 12563, + 12548, 12533, 12518, 12503, 12488, 12473, 12458, 12443, + 12428, 12413, 12398, 12383, 12368, 12353, 12338, 12323, + 12309, 12294, 12279, 12264, 12249, 12234, 12220, 12205, + 12190, 12175, 12160, 12146, 12131, 12116, 12102, 12087, + 12072, 12058, 12043, 12028, 12014, 11999, 11985, 11970, + 11955, 11941, 11926, 11912, 11897, 11883, 11868, 11854, + 11840, 11825, 11811, 11796, 11782, 11767, 11753, 11739, + 11724, 11710, 11696, 11682, 11667, 11653, 11639, 11625, + 11610, 11596, 11582, 11568, 11554, 11539, 11525, 11511, + 11497, 11483, 11469, 11455, 11441, 11427, 11413, 11399, + 11385, 11371, 11357, 11343, 11329, 11315, 11301, 11287, + 11273, 11259, 11245, 11232, 11218, 11204, 11190, 11176, + 11163, 11149, 11135, 11121, 11108, 11094, 11080, 11067, + 11053, 11039, 11026, 11012, 10999, 10985, 10971, 10958, + 10944, 10931, 10917, 10904, 10890, 10877, 10863, 10850, + 10836, 10823, 10810, 10796, 10783, 10770, 10756, 10743, + 10730, 10716, 10703, 10690, 10676, 10663, 10650, 10637, + 10624, 10610, 10597, 10584, 10571, 10558, 10545, 10532, + 10519, 10506, 10492, 10479, 10466, 10453, 10440, 10427, + 10414, 10402, 10389, 10376, 10363, 10350, 10337, 10324, + 10311, 10299, 10286, 10273, 10260, 10247, 10235, 10222, + 10209, 10196, 10184, 10171, 10158, 10146, 10133, 10121, + 10108, 10095, 10083, 10070, 10058, 10045, 10033, 10020, + 10008, 9995, 9983, 9970, 9958, 9945, 9933, 9921, + 9908, 9896, 9884, 9871, 9859, 9847, 9834, 9822, + 9810, 9798, 9785, 9773, 9761, 9749, 9737, 9725, + 9712, 9700, 9688, 9676, 9664, 9652, 9640, 9628, + 9616, 9604, 9592, 9580, 9568, 9556, 9544, 9532, + 9521, 9509, 9497, 9485, 9473, 9461, 9450, 9438, + 9426, 9414, 9403, 9391, 9379, 9367, 9356, 9344, + 9332, 9321, 9309, 9298, 9286, 9275, 9263, 9251, + 9240, 9228, 9217, 9205, 9194, 9183, 9171, 9160, + 9148, 9137, 9126, 9114, 9103, 9092, 9080, 9069, + 9058, 9047, 9035, 9024, 9013, 9002, 8990, 8979, + 8968, 8957, 8946, 8935, 8924, 8913, 8902, 8891, + 8880, 8869, 8858, 8847, 8836, 8825, 8814, 8803, + 8792, 8781, 8770, 8759, 8749, 8738, 8727, 8716, + 8705, 8695, 8684, 8673, 8662, 8652, 8641, 8630, + 8620, 8609, 8599, 8588, 8577, 8567, 8556, 8546, + 8535, 8525, 8514, 8504, 8493, 8483, 8472, 8462, + 8452, 8441, 8431, 8421, 8410, 8400, 8390, 8379, + 8369, 8359, 8349, 8338, 8328, 8318, 8308, 8298, + 8288, 8277, 8267, 8257, 8247, 8237, 8227, 8217, + 8207, 8197, 8187, 8177, 8167, 8157, 8147, 8137, + 8128, 8118, 8108, 8098, 8088, 8078, 8069, 8059, + 8049, 8039, 8030, 8020, 8010, 8001, 7991, 7981, + 7972, 7962, 7952, 7943, 7933, 7924, 7914, 7905, + 7895, 7886, 7876, 7867, 7857, 7848, 7839, 7829, + 7820, 7811, 7801, 7792, 7783, 7773, 7764, 7755, + 7746, 7736, 7727, 7718, 7709, 7700, 7691, 7681, + 7672, 7663, 7654, 7645, 7636, 7627, 7618, 7609, + 7600, 7591, 7582, 7573, 7564, 7555, 7547, 7538, + 7529, 7520, 7511, 7502, 7494, 7485, 7476, 7467, + 7459, 7450, 7441, 7433, 7424, 7415, 7407, 7398, + 7390, 7381, 7373, 7364, 7355, 7347, 7338, 7330, + 7322, 7313, 7305, 7296, 7288, 7280, 7271, 7263, + 7255, 7246, 7238, 7230, 7221, 7213, 7205, 7197, + 7189, 7180, 7172, 7164, 7156, 7148, 7140, 7132, + 7124, 7116, 7108, 7100, 7092, 7084, 7076, 7068, + 7060, 7052, 7044, 7036, 7029, 7021, 7013, 7005, + 6997, 6990, 6982, 6974, 6966, 6959, 6951, 6943, + 6936, 6928, 6920, 6913, 6905, 6898, 6890, 6883, + 6875, 6868, 6860, 6853, 6845, 6838, 6830, 6823, + 6815, 6808, 6801, 6793, 6786, 6779, 6772, 6764, + 6757, 6750, 6743, 6735, 6728, 6721, 6714, 6707, + 6700, 6693, 6686, 6678, 6671, 6664, 6657, 6650, + 6643, 6636, 6630, 6623, 6616, 6609, 6602, 6595, + 6588, 6581, 6575, 6568, 6561, 6554, 6548, 6541, + 6534, 6527, 6521, 6514, 6507, 6501, 6494, 6488, + 6481, 6475, 6468, 6461, 6455, 6448, 6442, 6436, + 6429, 6423, 6416, 6410, 6404, 6397, 6391, 6385, + 6378, 6372, 6366, 6359, 6353, 6347, 6341, 6335, + 6329, 6322, 6316, 6310, 6304, 6298, 6292, 6286, + 6280, 6274, 6268, 6262, 6256, 6250, 6244, 6238, + 6232, 6226, 6221, 6215, 6209, 6203, 6197, 6192, + 6186, 6180, 6174, 6169, 6163, 6157, 6152, 6146, + 6140, 6135, 6129, 6124, 6118, 6113, 6107, 6102, + 6096, 6091, 6085, 6080, 6074, 6069, 6064, 6058, + 6053, 6048, 6042, 6037, 6032, 6027, 6021, 6016, + 6011, 6006, 6001, 5995, 5990, 5985, 5980, 5975, + 5970, 5965, 5960, 5955, 5950, 5945, 5940, 5935, + 5930, 5925, 5920, 5915, 5911, 5906, 5901, 5896, + 5891, 5887, 5882, 5877, 5872, 5868, 5863, 5858, + 5854, 5849, 5845, 5840, 5835, 5831, 5826, 5822, + 5817, 5813, 5808, 5804, 5799, 5795, 5791, 5786, + 5782, 5778, 5773, 5769, 5765, 5760, 5756, 5752, + 5748, 5743, 5739, 5735, 5731, 5727, 5723, 5719, + 5714, 5710, 5706, 5702, 5698, 5694, 5690, 5686, + 5682, 5678, 5675, 5671, 5667, 5663, 5659, 5655, + 5651, 5648, 5644, 5640, 5636, 5633, 5629, 5625, + 5622, 5618, 5614, 5611, 5607, 5604, 5600, 5596, + 5593, 5589, 5586, 5582, 5579, 5576, 5572, 5569, + 5565, 5562, 5559, 5555, 5552, 5549, 5545, 5542, + 5539, 5536, 5532, 5529, 5526, 5523, 5520, 5517, + 5514, 5511, 5507, 5504, 5501, 5498, 5495, 5492, + 5489, 5486, 5484, 5481, 5478, 5475, 5472, 5469, + 5466, 5464, 5461, 5458, 5455, 5452, 5450, 5447, + 5444, 5442, 5439, 5436, 5434, 5431, 5429, 5426, + 5424, 5421, 5419, 5416, 5414, 5411, 5409, 5406, + 5404, 5401, 5399, 5397, 5394, 5392, 5390, 5388, + 5385, 5383, 5381, 5379, 5376, 5374, 5372, 5370, + 5368, 5366, 5364, 5362, 5360, 5358, 5356, 5354, + 5352, 5350, 5348, 5346, 5344, 5342, 5340, 5338, + 5336, 5335, 5333, 5331, 5329, 5328, 5326, 5324, + 5322, 5321, 5319, 5317, 5316, 5314, 5313, 5311, + 5309, 5308, 5306, 5305, 5303, 5302, 5301, 5299, + 5298, 5296, 5295, 5294, 5292, 5291, 5290, 5288, + 5287, 5286, 5285, 5283, 5282, 5281, 5280, 5279, + 5278, 5276, 5275, 5274, 5273, 5272, 5271, 5270, + 5269, 5268, 5267, 5266, 5265, 5265, 5264, 5263, + 5262, 5261, 5260, 5260, 5259, 5258, 5257, 5257, + 5256, 5255, 5255, 5254, 5253, 5253, 5252, 5251, + 5251, 5250, 5250, 5249, 5249, 5248, 5248, 5247, + 5247, 5247, 5246, 5246, 5246, 5245, 5245, 5245, + 5244, 5244, 5244, 5244, 5243, 5243, 5243, 5243, + 5243, 5243, 5243, 5243, 5242, 5242, 5242, 5242, +}; diff --git a/fmdriver/fmdriver.h b/fmdriver/fmdriver.h index aebe27e..b31c31e 100644 --- a/fmdriver/fmdriver.h +++ b/fmdriver/fmdriver.h @@ -101,11 +101,17 @@ struct fmdriver_work { uint8_t ssg_noise_freq; struct fmdriver_track_status track_status[FMDRIVER_TRACK_NUM]; uint8_t loop_cnt; + // timerb value + uint8_t timerb; // current timerb count uint32_t timerb_cnt; - // loop length + // current timerb count, reset on loop + uint32_t timerb_cnt_loop; + // loop length, calculated before playing uint32_t loop_timerb_cnt; // fm3ex part map + bool playing; + bool paused; }; #endif // MYON_FMDRIVER_H_INCLUDED diff --git a/fmdriver/fmdriver_fmp.c b/fmdriver/fmdriver_fmp.c index 41d0a48..5e01089 100644 --- a/fmdriver/fmdriver_fmp.c +++ b/fmdriver/fmdriver_fmp.c @@ -304,6 +304,7 @@ static bool fmp_cmd62_tempo(struct fmdriver_work *work, uint8_t tempo = fmp_part_cmdload(fmp, part);
fmp->timerb_bak = tempo;
fmp->timerb = tempo;
+ work->timerb = fmp->timerb;
fmp_set_tempo(work, fmp);
return true;
}
@@ -876,6 +877,7 @@ static bool fmp_cmd74_loop(struct fmdriver_work *work, // 248c
fmp->loop_cnt++;
work->loop_cnt = fmp->loop_cnt;
+ work->timerb_cnt_loop = 0;
fmp->part_loop_bit = fmp->part_playing_bit;
// al=2; 1b64();
}
@@ -2854,6 +2856,7 @@ static void fmp_timerb(struct fmdriver_work *work, struct driver_fmp *fmp) { if (fmp->status.stopped) {
// TODO: stopped
// jmp 18c7
+ work->playing = false;
}
// 1829
if (!--fmp->clock_divider) {
@@ -2989,6 +2992,7 @@ static void fmp_init_parts(struct fmdriver_work *work, // work->opna_writereg(work, 0x110, 0x80);
fmp->timerb = 0xca;
+ work->timerb = fmp->timerb;
fmp->timerb_bak = 0xca;
// 3c79
@@ -3150,7 +3154,10 @@ static void fmp_opna_interrupt(struct fmdriver_work *work) { struct driver_fmp *fmp = (struct driver_fmp *)work->driver;
if (work->opna_status(work, 0) & 0x02) {
fmp_timerb(work, fmp);
- work->timerb_cnt++;
+ if (work->playing) {
+ work->timerb_cnt++;
+ work->timerb_cnt_loop++;
+ }
}
}
@@ -3495,6 +3502,7 @@ void fmp_init(struct fmdriver_work *work, struct driver_fmp *fmp) { fmp_work_status_init(work, fmp);
fmdriver_fillpcmname(work->pcmname[0], fmp->pvi_name);
fmdriver_fillpcmname(work->pcmname[1], fmp->ppz_name);
+ work->playing = true;
}
// 4235
diff --git a/fmdriver/fmdriver_pmd.c b/fmdriver/fmdriver_pmd.c index 14459a5..ac2cad2 100644 --- a/fmdriver/fmdriver_pmd.c +++ b/fmdriver/fmdriver_pmd.c @@ -353,8 +353,8 @@ static void pmd_calc_tempo_rev( int timerb = 0; if (tempo) { timerb = 0x112c / tempo; - if (0x112c % tempo) timerb++; timerb = 0x100 - timerb; + if ((0x112c % tempo) & 0x80) timerb--; if (timerb < 0) timerb = 0; } pmd->timerb = timerb; @@ -377,6 +377,7 @@ static void pmd_reset_timer( struct driver_pmd *pmd ) { pmd->timerb = 200; + work->timerb = pmd->timerb; pmd->timerb_bak = pmd->timerb; pmd_calc_tempo(pmd); pmd_timerb_write(work, pmd); @@ -2345,6 +2346,7 @@ static void pmd_cmdfc_tempo( pmd->tempo_bak = tempo; pmd_calc_tempo_rev(pmd); } + work->timerb = pmd->timerb; } // 236b @@ -5537,9 +5539,12 @@ static void pmd_proc_parts( } // 130d if (!pmd->loop.looped || !pmd->loop.ended || pmd->loop.env) { + work->timerb_cnt_loop = 0; if (++pmd->status2 == 0xff) pmd->status2 = 1; } else { pmd->status2 = 0xff; + // stop + work->playing = false; } work->loop_cnt = pmd->status2; } @@ -5627,7 +5632,10 @@ static void pmd_timer( } if (status & 2) { pmd_timerb(work, pmd); - work->timerb_cnt++; + if (work->playing) { + work->timerb_cnt++; + work->timerb_cnt_loop++; + } } } @@ -5887,6 +5895,7 @@ void pmd_init(struct fmdriver_work *work, } fmdriver_fillpcmname(work->pcmname[0], pmd->ppcfile); fmdriver_fillpcmname(work->pcmname[1], pmd->ppzfile); + work->playing = true; } enum { diff --git a/fmdsp/fmdsp-vramlookup-neon.s b/fmdsp/fmdsp-vramlookup-neon.s index 3cfb957..c5d6db2 100644 --- a/fmdsp/fmdsp-vramlookup-neon.s +++ b/fmdsp/fmdsp-vramlookup-neon.s @@ -22,9 +22,8 @@ fmdsp_vramlookup_neon: push {lr} @ load palette vld3.8 {d26, d28, d30}, [r2]! - vld1.8 {d27}, [r2]! - vld1.8 {d29}, [r2]! - vld1.8 {d31}, [r2]! + vld3.8 {d27[0], d29[0], d31[0]}, [r2]! + vld3.8 {d27[1], d29[1], d31[1]}, [r2]! mov r14, #400 .loopcol: diff --git a/fmdsp/fmdsp.c b/fmdsp/fmdsp.c index fdec110..8f3499e 100644 --- a/fmdsp/fmdsp.c +++ b/fmdsp/fmdsp.c @@ -4,6 +4,8 @@ #include "fmdriver/fmdriver.h" #include <stdio.h> #include "libopna/opna.h" +#include "fmdsp_platform_info.h" +#include "version.h" fmdsp_vramlookup_type fmdsp_vramlookup_func = fmdsp_vramlookup_c; @@ -45,7 +47,7 @@ void fmdsp_init(struct fmdsp *fmdsp, const struct fmdsp_font *font98) { fmdsp->target_palette[i] = s_palettes[0][i]; } fmdsp->font98 = font98; - fmdsp->style = FMDSP_DISPSTYLE_DEFAULT; + fmdsp->style = FMDSP_DISPSTYLE_ORIGINAL; fmdsp->style_updated = true; } @@ -225,6 +227,7 @@ static void fmdsp_track_init_13(struct fmdsp *fmdsp, } } } + static void fmdsp_track_init_10(struct fmdsp *fmdsp, uint8_t *vram) { for (int y = 0; y < TRACK_H*FMDSP_TRACK_DISP_CNT_DEFAULT; y++) { @@ -234,7 +237,7 @@ static void fmdsp_track_init_10(struct fmdsp *fmdsp, } for (int i = 0; i < FMDSP_TRACK_DISP_CNT_DEFAULT; i++) { int t; - if (fmdsp->style == FMDSP_DISPSTYLE_DEFAULT) t = track_disp_table_default[i]; + if (fmdsp->style == FMDSP_DISPSTYLE_DEFAULT || fmdsp->style == FMDSP_DISPSTYLE_ORIGINAL) t = track_disp_table_default[i]; else if (fmdsp->style == FMDSP_DISPSTYLE_OPN) t = track_disp_table_opn[i]; else t = track_disp_table_ppz8[i]; if (t < 0) continue; @@ -270,6 +273,133 @@ static void fmdsp_track_init_10(struct fmdsp *fmdsp, s_bar, BAR_W, BAR_H, 3); } } + if (fmdsp->style == FMDSP_DISPSTYLE_ORIGINAL) { + vramblit(vram, LOGO_FM_X, LOGO_Y, s_logo_fm, LOGO_FM_W, LOGO_H); + vramblit(vram, LOGO_DS_X, LOGO_Y, s_logo_ds, LOGO_DS_W, LOGO_H); + vramblit(vram, LOGO_P_X, LOGO_Y, s_logo_p, LOGO_P_W, LOGO_H); + fmdsp_putline("MUS", vram, &font_fmdsp_small, TOP_MUS_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("IC", vram, &font_fmdsp_small, TOP_IC_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("F", vram, &font_fmdsp_small, TOP_F_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("ILE", vram, &font_fmdsp_small, TOP_ILE_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("SELECTOR", vram, &font_fmdsp_small, TOP_SELECTOR_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("&", vram, &font_fmdsp_small, TOP_AND_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("STATUS", vram, &font_fmdsp_small, TOP_STATUS_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("D", vram, &font_fmdsp_small, TOP_D_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline("ISPLAY", vram, &font_fmdsp_small, TOP_ISPLAY_X, TOP_MUSIC_Y, 2, true); + vramblit(vram, TOP_VER_X, VER_Y, s_ver, VER_W, VER_H); + fmdsp_putline(FMPLAYER_VERSION_0 ".", vram, &font_fmdsp_small, VER_0_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline(FMPLAYER_VERSION_1 ".", vram, &font_fmdsp_small, VER_1_X, TOP_MUSIC_Y, 2, true); + fmdsp_putline(FMPLAYER_VERSION_2, vram, &font_fmdsp_small, VER_2_X, TOP_MUSIC_Y, 2, true); + + vramblit(vram, TOP_MUS_X, TOP_TEXT_Y, s_text, TOP_TEXT_W, TOP_TEXT_H); + + fmdsp_putline("DR", vram, &font_fmdsp_small, DRIVER_TEXT_X, DRIVER_TEXT_Y, 7, true); + fmdsp_putline("IVER", vram, &font_fmdsp_small, DRIVER_TEXT_2_X, DRIVER_TEXT_Y, 7, true); + vramblit_color(vram, DRIVER_TRI_X, DRIVER_TRI_Y, s_filebar_tri, FILEBAR_TRI_W, FILEBAR_TRI_H, 7); + vramblit(vram, CURL_LEFT_X, CURL_Y, s_curl_left, CURL_W, CURL_H); + vramblit(vram, CURL_RIGHT_X, CURL_Y, s_curl_right, CURL_W, CURL_H); + + for (int x = 0; x < 82; x++) { + vram[14*PC98_W+312+x] = 2; + } + for (int x = 0; x < 239; x++) { + vram[14*PC98_W+395+x] = 7; + } + for (int x = 0; x < TIME_BAR_W; x++) { + for (int y = 0; y < TIME_BAR_H; y++) { + vram[(TIME_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + vram[(CLOCK_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + vram[(TIMERB_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + vram[(LOOPCNT_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + vram[(VOLDOWN_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + vram[(PGMNUM_Y-2+y)*PC98_W+TIME_BAR_X+x] = 2; + } + } + for (int i = 0; i < 6; i++) { + vramblit(vram, TIME_TRI_X, TIME_Y+8+19*i, s_filebar_tri, FILEBAR_TRI_W, FILEBAR_TRI_H); + } + fmdsp_putline("PASSED", vram, &font_fmdsp_small, TIME_TEXT_X, TIME_Y-2, 2, true); + fmdsp_putline("T", vram, &font_fmdsp_small, TIME_TEXT_X+11, TIME_Y+5, 2, true); + fmdsp_putline("IME", vram, &font_fmdsp_small, TIME_TEXT_X+15, TIME_Y+5, 2, true); + fmdsp_putline("CLOCK", vram, &font_fmdsp_small, TIME_TEXT_X, CLOCK_Y-2, 2, true); + fmdsp_putline(" COUNT", vram, &font_fmdsp_small, TIME_TEXT_X, CLOCK_Y+5, 2, true); + fmdsp_putline("T", vram, &font_fmdsp_small, TIME_TEXT_X, TIMERB_Y-2, 2, true); + fmdsp_putline("IMER", vram, &font_fmdsp_small, TIME_TEXT_X+4, TIMERB_Y-2, 2, true); + fmdsp_putline(" CYCLE", vram, &font_fmdsp_small, TIME_TEXT_X, TIMERB_Y+5, 2, true); + fmdsp_putline("LOOP", vram, &font_fmdsp_small, TIME_TEXT_X, LOOPCNT_Y-2, 2, true); + fmdsp_putline(" COUNT", vram, &font_fmdsp_small, TIME_TEXT_X, LOOPCNT_Y+5, 2, true); + fmdsp_putline("VOLUME", vram, &font_fmdsp_small, TIME_TEXT_X, VOLDOWN_Y-2, 2, true); + fmdsp_putline(" DOWN", vram, &font_fmdsp_small, TIME_TEXT_X, VOLDOWN_Y+5, 2, true); + fmdsp_putline("PGM", vram, &font_fmdsp_small, TIME_TEXT_X, PGMNUM_Y-2, 2, true); + fmdsp_putline("NUMBER", vram, &font_fmdsp_small, TIME_TEXT_X, PGMNUM_Y+5, 2, true); + + for (int x = 0; x < TIME_BAR_W; x++) { + for (int y = 0; y < TIME_BAR_H; y++) { + vram[(CPU_Y+y)*PC98_W+CPU_BAR_X+x] = 2; + } + } + fmdsp_putline("CPU", vram, &font_fmdsp_small, CPU_X, CPU_Y, 2, true); + fmdsp_putline("POWER", vram, &font_fmdsp_small, CPU_X+17, CPU_Y, 2, true); + fmdsp_putline("COUNT", vram, &font_fmdsp_small, CPU_X+17, CPU_Y+7, 2, true); + vramblit(vram, CPU_TRI_X, CPU_TRI_Y, s_filebar_tri, FILEBAR_TRI_W, FILEBAR_TRI_H); + for (int x = 0; x < TIME_BAR_W; x++) { + for (int y = 0; y < TIME_BAR_H; y++) { + vram[(CPU_Y+y)*PC98_W+FPS_BAR_X+x] = 2; + } + } + fmdsp_putline("FRAMES", vram, &font_fmdsp_small, FPS_X, CPU_Y, 2, true); + fmdsp_putline("PER", vram, &font_fmdsp_small, FPS_X+32, CPU_Y, 2, true); + fmdsp_putline("SECOND", vram, &font_fmdsp_small, FPS_X+17, CPU_Y+7, 2, true); + vramblit(vram, FPS_TRI_X, CPU_TRI_Y, s_filebar_tri, FILEBAR_TRI_W, FILEBAR_TRI_H); + for (int x = 0; x < 322; x++) { + vram[132*PC98_W+312+x] = 7; + } + fmdsp_putline("SENS", vram, &font_fmdsp_small, SPECTRUM_X-40, SPECTRUM_Y-6, 7, true); + fmdsp_putline("-48", vram, &font_fmdsp_small, SPECTRUM_X-19, SPECTRUM_Y-6, 7, true); + fmdsp_putline("0", vram, &font_fmdsp_small, SPECTRUM_X-9, SPECTRUM_Y-63, 7, true); + fmdsp_putline("dB", vram, &font_fmdsp_small, SPECTRUM_X-14, SPECTRUM_Y-71, 7, true); + fmdsp_putline("SPECTRUM", vram, &font_fmdsp_small, SPECTRUM_X+197, SPECTRUM_Y-71, 7, true); + fmdsp_putline("ANAL", vram, &font_fmdsp_small, SPECTRUM_X+241, SPECTRUM_Y-71, 7, true); + fmdsp_putline("YzER", vram, &font_fmdsp_small, SPECTRUM_X+260, SPECTRUM_Y-71, 7, true); + for (int y = 0; y < 63; y++) { + vram[(SPECTRUM_Y-y)*PC98_W+SPECTRUM_X-2] = 2; + if (!(y % 2)) { + vram[(SPECTRUM_Y-y)*PC98_W+SPECTRUM_X-3] = 2; + } + if (!(y % 8)) { + vram[(SPECTRUM_Y-y)*PC98_W+SPECTRUM_X-4] = 2; + } + } + fmdsp_putline("FREQ", vram, &font_fmdsp_small, SPECTRUM_X-24, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 17; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+1+2*x] = 1; + } + fmdsp_putline("250", vram, &font_fmdsp_small, SPECTRUM_X+36, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 15; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+52+2*x] = 1; + } + fmdsp_putline("500", vram, &font_fmdsp_small, SPECTRUM_X+83, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 17; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+99+2*x] = 1; + } + fmdsp_putline("1", vram, &font_fmdsp_small, SPECTRUM_X+133, SPECTRUM_Y+1, 1, true); + fmdsp_putline("k", vram, &font_fmdsp_small, SPECTRUM_X+133+6, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 19; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+144+2*x] = 1; + } + fmdsp_putline("2k", vram, &font_fmdsp_small, SPECTRUM_X+183, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 18; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+193+2*x] = 1; + } + fmdsp_putline("4k", vram, &font_fmdsp_small, SPECTRUM_X+230, SPECTRUM_Y+1, 1, true); + for (int x = 0; x < 20; x++) { + vram[(SPECTRUM_Y+4)*PC98_W+SPECTRUM_X+240+2*x] = 1; + } + fmdsp_putline("ON/OFF", vram, &font_fmdsp_small, LEVEL_TEXT_X, LEVEL_TEXT_Y, 1, true); + fmdsp_putline("PANPOT", vram, &font_fmdsp_small, LEVEL_TEXT_X, LEVEL_TEXT_Y+8, 1, true); + fmdsp_putline("PROGRAM", vram, &font_fmdsp_small, LEVEL_TEXT_X-5, LEVEL_TEXT_Y+16, 1, true); + fmdsp_putline("KEYCODE", vram, &font_fmdsp_small, LEVEL_TEXT_X-5, LEVEL_TEXT_Y+23, 1, true); + } } void fmdsp_vram_init(struct fmdsp *fmdsp, @@ -551,7 +681,8 @@ static void fmdsp_track_without_key( fmdsp_putline("TN:", vram, &font_fmdsp_small, TDETAIL_TN_X, y+6, 1, true); snprintf(numbuf, sizeof(numbuf), "%03d", track->tonenum); fmdsp_putline(numbuf, vram, &font_fmdsp_small, TDETAIL_TN_V_X, y+6, 1, true); - fmdsp_putline("VL:", vram, &font_fmdsp_small, TDETAIL_VL_X, y+6, 1, true); + fmdsp_putline("Vl", vram, &font_fmdsp_small, TDETAIL_VL_X, y+6, 1, true); + fmdsp_putline(":", vram, &font_fmdsp_small, TDETAIL_VL_C_X, y+6, 1, true); snprintf(numbuf, sizeof(numbuf), "%03d", track->volume); fmdsp_putline(numbuf, vram, &font_fmdsp_small, TDETAIL_VL_V_X, y+6, 1, true); fmdsp_putline("GT:", vram, &font_fmdsp_small, TDETAIL_GT_X, y+6, 1, true); @@ -583,45 +714,50 @@ static void fmdsp_track_without_key( static void fmdsp_update_10(struct fmdsp *fmdsp, const struct fmdriver_work *work, const struct opna *opna, - uint8_t *vram) { - for (int y = 0; y < 320; y++) { - for (int x = 320; x < PC98_W; x++) { - vram[y*PC98_W+x] = 0; + uint8_t *vram, + struct fmplayer_fft_input_data *idata) { + if (fmdsp->style != FMDSP_DISPSTYLE_ORIGINAL) { + for (int y = 0; y < 320; y++) { + for (int x = 320; x < PC98_W; x++) { + vram[y*PC98_W+x] = 0; + } } } for (int it = 0; it < FMDSP_TRACK_DISP_CNT_DEFAULT; it++) { int t; - if (fmdsp->style == FMDSP_DISPSTYLE_DEFAULT) t = track_disp_table_default[it]; + if (fmdsp->style == FMDSP_DISPSTYLE_DEFAULT || fmdsp->style == FMDSP_DISPSTYLE_ORIGINAL) t = track_disp_table_default[it]; else if (fmdsp->style == FMDSP_DISPSTYLE_OPN) t = track_disp_table_opn[it]; else t = track_disp_table_ppz8[it]; if (t < 0) continue; const struct fmdriver_track_status *track = &work->track_status[t]; - if (((track->info == FMDRIVER_TRACK_INFO_PPZ8) - || (track->info == FMDRIVER_TRACK_INFO_PDZF)) - && track->ppz8_ch) { - fmdsp_track_info_ppz8(work->ppz8, track->ppz8_ch-1, - 320, TRACK_H*it+6, vram); - } else { - switch (track_type_table[t].type) { - case FMDRIVER_TRACKTYPE_FM: - fmdsp_track_info_fm(opna, - track_type_table[t].num-1, - track->info == FMDRIVER_TRACK_INFO_FM3EX ? track->fmslotmask : 0, - 320, TRACK_H*it+6, vram); - break; - case FMDRIVER_TRACKTYPE_SSG: - fmdsp_track_info_ssg(opna, - track_type_table[t].num-1, - 320, TRACK_H*it+6, vram); - break; - case FMDRIVER_TRACKTYPE_ADPCM: - fmdsp_track_info_adpcm(opna, 320, TRACK_H*it+6, vram); - break; - case FMDRIVER_TRACKTYPE_PPZ8: - fmdsp_track_info_ppz8(work->ppz8, track_type_table[t].num-1, + if (fmdsp->style != FMDSP_DISPSTYLE_ORIGINAL) { + if (((track->info == FMDRIVER_TRACK_INFO_PPZ8) + || (track->info == FMDRIVER_TRACK_INFO_PDZF)) + && track->ppz8_ch) { + fmdsp_track_info_ppz8(work->ppz8, track->ppz8_ch-1, 320, TRACK_H*it+6, vram); - break; + } else { + switch (track_type_table[t].type) { + case FMDRIVER_TRACKTYPE_FM: + fmdsp_track_info_fm(opna, + track_type_table[t].num-1, + track->info == FMDRIVER_TRACK_INFO_FM3EX ? track->fmslotmask : 0, + 320, TRACK_H*it+6, vram); + break; + case FMDRIVER_TRACKTYPE_SSG: + fmdsp_track_info_ssg(opna, + track_type_table[t].num-1, + 320, TRACK_H*it+6, vram); + break; + case FMDRIVER_TRACKTYPE_ADPCM: + fmdsp_track_info_adpcm(opna, 320, TRACK_H*it+6, vram); + break; + case FMDRIVER_TRACKTYPE_PPZ8: + fmdsp_track_info_ppz8(work->ppz8, track_type_table[t].num-1, + 320, TRACK_H*it+6, vram); + break; + } } } fmdsp_track_without_key(fmdsp, work, track, t, TRACK_H*it, vram); @@ -642,6 +778,167 @@ static void fmdsp_update_10(struct fmdsp *fmdsp, } } } + if (fmdsp->style == FMDSP_DISPSTYLE_ORIGINAL) { + // control status + bool playing = work->playing && !work->paused; + bool stopped = !work->playing; + bool paused = work->paused; + vramblit_color(vram, PLAY_X, PLAY_Y, s_play, PLAY_W, PLAY_H, playing ? 2 : 3); + vramblit_color(vram, STOP_X, STOP_Y, s_stop, STOP_W, STOP_H, stopped ? 2 : 3); + vramblit_color(vram, PAUSE_X, PAUSE_Y, s_pause, PAUSE_W, PAUSE_H, paused ? 2 : 3); + vramblit(vram, FADE_X, FADE_Y, s_fade, FADE_W, FADE_H); + vramblit(vram, FF_X, FF_Y, s_ff, FF_W, FF_H); + vramblit(vram, REW_X, REW_Y, s_rew, REW_W, REW_H); + vramblit(vram, FLOPPY_X, FLOPPY_Y, s_floppy, FLOPPY_W, FLOPPY_H); + const uint8_t *num[8]; + // passed time + { + uint64_t frames = opna->generated_frames; + int ssec = (int)(frames % 55467u) * 100 / 55467; + uint64_t sec = frames / 55467u; + uint64_t min = sec / 60u; + sec %= 60u; + num[0] = s_num[(min/10)%10]; + num[1] = s_num[min%10]; + vramblit(vram, TIME_X+NUM_W*0, TIME_Y, num[0], NUM_W, NUM_H); + vramblit(vram, TIME_X+NUM_W*1, TIME_Y, num[1], NUM_W, NUM_H); + vramblit(vram, TIME_X+NUM_W*2, TIME_Y, s_num_colon[sec%2u], NUM_W, NUM_H); + num[0] = s_num[(sec/10)%10]; + num[1] = s_num[sec%10]; + vramblit(vram, TIME_X+NUM_W*3, TIME_Y, num[0], NUM_W, NUM_H); + vramblit(vram, TIME_X+NUM_W*4, TIME_Y, num[1], NUM_W, NUM_H); + vramblit(vram, TIME_X+NUM_W*5, TIME_Y, s_num_bar, NUM_W, NUM_H); + num[0] = s_num[(ssec/10)%10]; + num[1] = s_num[ssec%10]; + vramblit(vram, TIME_X+NUM_W*6, TIME_Y, num[0], NUM_W, NUM_H); + vramblit(vram, TIME_X+NUM_W*7, TIME_Y, num[1], NUM_W, NUM_H); + } + // clock count + { + uint64_t clock = work->timerb_cnt; + for (int i = 0; i < 8; i++) { + num[7-i] = s_num[clock%10u]; + clock /= 10u; + } + for (int i = 0; i < 8; i++) { + vramblit(vram, TIME_X+NUM_W*i, CLOCK_Y, num[i], NUM_W, NUM_H); + } + } + // timerb + { + uint8_t timerb = work->timerb; + for (int i = 0; i < 3; i++) { + num[2-i] = s_num[timerb%10]; + timerb /= 10; + } + for (int i = 0; i < 3; i++) { + vramblit(vram, TIME_X+NUM_W*(5+i), TIMERB_Y, num[i], NUM_W, NUM_H); + } + } + // loop count + { + uint8_t loop = work->loop_cnt; + for (int i = 0; i < 4; i++) { + num[3-i] = s_num[loop%10]; + loop /= 10; + } + for (int i = 0; i < 4; i++) { + vramblit(vram, TIME_X+NUM_W*(4+i), LOOPCNT_Y, num[i], NUM_W, NUM_H); + } + } + // + int pos = 0; + if (work->loop_timerb_cnt) pos = work->timerb_cnt_loop * (72+1-4) / work->loop_timerb_cnt; + for (int x = 0; x < 72; x++) { + if (x == 0 || x == 36 || x == 71) { + vram[(70-2)*PC98_W+352+x*2] = 7; + } else if (!(x % 9)) { + vram[(70-2)*PC98_W+352+x*2] = 3; + } + uint8_t c = 3; + if (work->playing && ((pos <= x) && (x < (pos+4)))) c = 2; + for (int y = 0; y < 4; y++) { + vram[(70+y)*PC98_W+352+x*2] = c; + } + } + for (int x = 0; x < 16; x++) { + for (int y = 0; y < 4; y++) { + vram[(70+y)*PC98_W+496+x] = work->loop_cnt ? 7 : 3; + } + } + // cpu + int cpuusage = fmdsp->cpuusage; + for (int i = 0; i < 3; i++) { + num[2-i] = s_num[cpuusage % 10]; + cpuusage /= 10; + } + for (int i = 0; i < 3; i++) { + vramblit(vram, CPU_NUM_X+NUM_W*i, CPU_NUM_Y, num[i], NUM_W, NUM_H); + } + // fps + int fps = fmdsp->fps; + for (int i = 0; i < 3; i++) { + num[2-i] = s_num[fps % 10]; + fps /= 10; + } + for (int i = 0; i < 3; i++) { + vramblit(vram, FPS_NUM_X+NUM_W*i, CPU_NUM_Y, num[i], NUM_W, NUM_H); + } + // circle + for (int y = 0; y < CIRCLE_H; y++) { + for (int x = 0; x < CIRCLE_W; x++) { + int c = 0; + int clock = (work->timerb_cnt / 8) % 8; + int p; + if ((p = s_circle[y*CIRCLE_W+x])) { + c = (work->playing && (!work->paused || (fmdsp->framecnt % 60) < 30) && (p == (clock + 1))) ? 2 : 3; + } + vram[(CIRCLE_Y+y)*PC98_W+CIRCLE_X+x] = c; + } + } + // fft + struct fmplayer_fft_disp_data ddata; + fft_calc(&ddata, idata); + for (int x = 0; x < FFTDISPLEN; x++) { + for (int y = 0; y < 32; y++) { + int px = SPECTRUM_X+x*4; + int py = SPECTRUM_Y-y*2; + int c = y < ddata.buf[x] ? 2 : 3; + vram[py*PC98_W+px+0] = c; + vram[py*PC98_W+px+1] = c; + vram[py*PC98_W+px+2] = c; + } + } + for (int i = 0; i < FFTDISPLEN; i++) { + if (fmdsp->fftdata[i] <= ddata.buf[i]) { + fmdsp->fftdata[i] = ddata.buf[i]; + fmdsp->fftcnt[i] = 30; + } else { + if (fmdsp->fftcnt[i]) { + fmdsp->fftcnt[i]--; + } else { + if (fmdsp->fftdata[i]) { + if (fmdsp->fftdropdiv[i]) { + fmdsp->fftdropdiv[i]--; + } else { + static const uint8_t divtab[16] = { + 32, 16, 8, 8, 4, 4, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2, + }; + fmdsp->fftdropdiv[i] = divtab[fmdsp->fftdata[i] / 2]; + fmdsp->fftdata[i]--; + } + } + } + } + } + for (int x = 0; x < FFTDISPLEN; x++) { + int px = SPECTRUM_X+x*4; + int py = SPECTRUM_Y-fmdsp->fftdata[x]*2; + vram[py*PC98_W+px+0] = 7; + vram[py*PC98_W+px+1] = 7; + vram[py*PC98_W+px+2] = 7; + } + } } static void fmdsp_update_13(struct fmdsp *fmdsp, const struct fmdriver_work *work, @@ -701,7 +998,8 @@ static void fmdsp_update_13(struct fmdsp *fmdsp, void fmdsp_update(struct fmdsp *fmdsp, const struct fmdriver_work *work, const struct opna *opna, - uint8_t *vram) { + uint8_t *vram, + struct fmplayer_fft_input_data *idata) { if (fmdsp->style_updated) { if (fmdsp->style == FMDSP_DISPSTYLE_13) { fmdsp_track_init_13(fmdsp, vram); @@ -739,9 +1037,14 @@ void fmdsp_update(struct fmdsp *fmdsp, if (fmdsp->style == FMDSP_DISPSTYLE_13) { fmdsp_update_13(fmdsp, work, opna, vram); } else { - fmdsp_update_10(fmdsp, work, opna, vram); + fmdsp_update_10(fmdsp, work, opna, vram, idata); } fmdsp_palette_fade(fmdsp); + if (!(fmdsp->framecnt % 30)) { + fmdsp->cpuusage = fmdsp_cpu_usage(); + fmdsp->fps = fmdsp_fps_30(); + } + fmdsp->framecnt++; } void fmdsp_vrampalette(struct fmdsp *fmdsp, const uint8_t *vram, uint8_t *vram32, int stride) { diff --git a/fmdsp/fmdsp.h b/fmdsp/fmdsp.h index 1aba5d9..6a98707 100644 --- a/fmdsp/fmdsp.h +++ b/fmdsp/fmdsp.h @@ -5,6 +5,7 @@ #include <stdbool.h> #include "font.h" #include "fmdriver/fmdriver.h" +#include "fft/fft.h" #ifdef __cplusplus extern "C" { @@ -18,10 +19,11 @@ enum { }; enum { - FMDSP_PALETTE_COLORS = 9 + FMDSP_PALETTE_COLORS = 10 }; enum FMDSP_DISPSTYLE { + FMDSP_DISPSTYLE_ORIGINAL, FMDSP_DISPSTYLE_DEFAULT, FMDSP_DISPSTYLE_OPN, FMDSP_DISPSTYLE_PPZ8, @@ -36,6 +38,12 @@ struct fmdsp { enum FMDSP_DISPSTYLE style; bool style_updated; bool masked[FMDRIVER_TRACK_NUM]; + uint8_t fftdata[FFTDISPLEN]; + uint8_t fftcnt[FFTDISPLEN]; + uint8_t fftdropdiv[FFTDISPLEN]; + uint64_t framecnt; + int cpuusage; + int fps; }; struct fmdriver_work; @@ -44,7 +52,9 @@ void fmdsp_vram_init(struct fmdsp *fmdsp, struct fmdriver_work *work, uint8_t *vram); void fmdsp_update(struct fmdsp *fmdsp, const struct fmdriver_work *work, - const struct opna *opna, uint8_t *vram); + const struct opna *opna, uint8_t *vram, + struct fmplayer_fft_input_data *idata + ); void fmdsp_vrampalette(struct fmdsp *fmdsp, const uint8_t *vram, uint8_t *vram32, int stride); void fmdsp_font_from_fontrom(uint8_t *font, const uint8_t *fontrom); void fmdsp_palette_set(struct fmdsp *fmdsp, int p); diff --git a/fmdsp/fmdsp_platform_info.h b/fmdsp/fmdsp_platform_info.h new file mode 100644 index 0000000..9afb2d6 --- /dev/null +++ b/fmdsp/fmdsp_platform_info.h @@ -0,0 +1,9 @@ +#ifndef MYON_FMPLAYER_FMDSP_PLATFORM_INFO_H_INCLUDED +#define MYON_FMPLAYER_FMDSP_PLATFORM_INFO_H_INCLUDED + +int fmdsp_cpu_usage(void); + +// call once per 30 frames to obtain fps +int fmdsp_fps_30(void); + +#endif // MYON_FMPLAYER_FMDSP_PLATFORM_INFO_H_INCLUDED diff --git a/fmdsp/fmdsp_platform_unix.c b/fmdsp/fmdsp_platform_unix.c new file mode 100644 index 0000000..446cee7 --- /dev/null +++ b/fmdsp/fmdsp_platform_unix.c @@ -0,0 +1,44 @@ +#include "fmdsp_platform_info.h" +#include <sys/times.h> +#include <time.h> +#include <limits.h> +#include <stdint.h> + +static struct { + clock_t lastall; + clock_t lastcpu; + struct timespec lasttimespec; +} g; + +int fmdsp_cpu_usage(void) { + struct tms tmsbuf; + clock_t all = times(&tmsbuf); + clock_t cpu = tmsbuf.tms_utime + tmsbuf.tms_stime; + clock_t percentage = 0; + clock_t alld = all - g.lastall; + clock_t cpud = cpu - g.lastcpu; + if (alld) percentage = cpud * 100 / alld; + g.lastall = all; + g.lastcpu = cpu; + if (!g.lastall) percentage = 0; + if (percentage > INT_MAX) percentage = INT_MAX; + if (percentage < 0) percentage = 0; + return percentage; +} + +int fmdsp_fps_30(void) { + struct timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + uint64_t fps = 0; + if (g.lasttimespec.tv_sec || g.lasttimespec.tv_nsec) { + uint64_t diffns = time.tv_sec - g.lasttimespec.tv_sec; + diffns *= 1000000000ull; + diffns += time.tv_nsec - g.lasttimespec.tv_nsec; + if (diffns) { + fps = 30ull * 1000000000ull / diffns; + } + } + g.lasttimespec = time; + if (fps > INT_MAX) fps = INT_MAX; + return fps; +} diff --git a/fmdsp/fmdsp_platform_win.c b/fmdsp/fmdsp_platform_win.c new file mode 100644 index 0000000..3dc4074 --- /dev/null +++ b/fmdsp/fmdsp_platform_win.c @@ -0,0 +1,57 @@ +#include "fmdsp_platform_info.h" +#include <stdint.h> +#include <limits.h> +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +static struct { + HANDLE currproc; + uint64_t lastall; + uint64_t lastcpu; + uint64_t lastfpstime; +} g; + +int fmdsp_cpu_usage(void) { + if (!g.currproc) g.currproc = GetCurrentProcess(); + FILETIME ft_sys, ft_creat, ft_exit, ft_kern, ft_user; + GetSystemTimeAsFileTime(&ft_sys); + GetProcessTimes(g.currproc, &ft_creat, &ft_exit, &ft_kern, &ft_user); + uint64_t all = ft_sys.dwHighDateTime; + all <<= 32; + all |= ft_sys.dwLowDateTime; + uint64_t kern = ft_kern.dwHighDateTime; + kern <<= 32; + kern |= ft_kern.dwLowDateTime; + uint64_t user = ft_user.dwHighDateTime; + user <<= 32; + user |= ft_user.dwLowDateTime; + uint64_t cpu = kern + user; + uint64_t alld = all - g.lastall; + uint64_t cpud = cpu - g.lastcpu; + int percentage = 0; + if (alld) percentage = cpud * 100 / alld; + g.lastall = all; + g.lastcpu = cpu; + if (!g.lastall) return 0; + if (percentage > INT_MAX) percentage = INT_MAX; + if (percentage < 0) percentage = 0; + return percentage; +} + +int fmdsp_fps_30(void) { + FILETIME ft; + GetSystemTimeAsFileTime(&ft); + uint64_t time = ft.dwHighDateTime; + time <<= 32; + time |= ft.dwLowDateTime; + uint64_t fps = 0; + if (g.lastfpstime) { + uint64_t diff = time - g.lastfpstime; + if (diff) { + fps = 30ull * 10000000ull / diff; + } + } + g.lastfpstime = time; + if (fps > INT_MAX) fps = INT_MAX; + return fps; +} diff --git a/fmdsp/fmdsp_sprites.h b/fmdsp/fmdsp_sprites.h index cb011a6..d9d71ac 100644 --- a/fmdsp/fmdsp_sprites.h +++ b/fmdsp/fmdsp_sprites.h @@ -3,36 +3,37 @@ enum { TRACK_H_S = 24, TNAME_W = 26, TNAME_H = 5, - TINFO_X = 48, - TDETAIL_X = 69, + TINFO_X = 47, + TDETAIL_X = 67, TDETAIL_KN_V_X = TDETAIL_X+13, - TDETAIL_TN_X = TDETAIL_KN_V_X+27, + TDETAIL_TN_X = TDETAIL_KN_V_X+28, TDETAIL_TN_V_X = TDETAIL_TN_X+13, TDETAIL_VL_X = TDETAIL_TN_V_X+20, - TDETAIL_VL_V_X = TDETAIL_VL_X+13, - TDETAIL_GT_X = TDETAIL_VL_V_X+20, + TDETAIL_VL_C_X = TDETAIL_VL_X+9, + TDETAIL_VL_V_X = TDETAIL_VL_X+12, + TDETAIL_GT_X = TDETAIL_VL_V_X+19, TDETAIL_GT_V_X = TDETAIL_GT_X+13, - TDETAIL_DT_X = TDETAIL_GT_V_X+20, + TDETAIL_DT_X = TDETAIL_GT_V_X+23, TDETAIL_DT_S_X = TDETAIL_DT_X+12, - TDETAIL_DT_V_X = TDETAIL_DT_S_X+4, - TDETAIL_M_X = 250, + TDETAIL_DT_V_X = TDETAIL_DT_S_X+5, + TDETAIL_M_X = 249, TDETAIL_M_V_X = TDETAIL_M_X+8, NUM_X = 31, NUM_W = 8, NUM_H = 11, - KEY_X = 8, + KEY_X = 7, KEY_Y = 14, KEY_W = 35, KEY_H = 17, KEY_S_OFFSET = KEY_W*4, KEY_H_S = KEY_H - 8, - KEY_LEFT_X = 1, + KEY_LEFT_X = 0, KEY_LEFT_W = 6, KEY_LEFT_S_OFFSET = KEY_LEFT_W*4, KEY_RIGHT_W = 11, KEY_RIGHT_S_OFFSET = KEY_RIGHT_W*4, KEY_OCTAVES = 8, - BAR_L_X = 68, + BAR_L_X = 66, BAR_L_W = 14, BAR_X = BAR_L_X + BAR_L_W, BAR_Y = 1, @@ -45,8 +46,8 @@ enum { PLAYING_Y = 324, PLAYING_W = 72, PLAYING_H = 9, - FILEBAR_X = 80, - FILEBAR_MUS_X = FILEBAR_X + 5, + FILEBAR_X = 78, + FILEBAR_MUS_X = FILEBAR_X + 6, FILEBAR_IC_X = FILEBAR_MUS_X + 14, FILEBAR_F_X = FILEBAR_IC_X + 11, FILEBAR_ILE_X = FILEBAR_F_X + 4, @@ -67,6 +68,104 @@ enum { PCM2FILENAME_X = PCM2FILETRI_X + 8, DT_SIGN_W = 3, DT_SIGN_H = 3, + SPECTRUM_X = 352, + SPECTRUM_Y = 207, + CPU_Y = 115, + CPU_X = 320, + CPU_BAR_X = CPU_X-6, + CPU_NUM_X = CPU_X+56, + CPU_NUM_Y = CPU_Y+2, + CPU_TRI_X = CPU_X+43, + CPU_TRI_Y = CPU_Y+10, + FPS_X = CPU_X+100, + FPS_BAR_X = FPS_X-6, + FPS_NUM_X = FPS_X+61, + FPS_TRI_X = FPS_X+48, + TIME_TEXT_X = 530, + TIME_X = TIME_TEXT_X+38, + TIME_BAR_X = TIME_TEXT_X-6, + TIME_TRI_X = TIME_TEXT_X+31, + TIME_BAR_W = 3, + TIME_BAR_H = 14, + TIME_Y = 22, + CLOCK_Y = TIME_Y+19, + TIMERB_Y = CLOCK_Y+19, + LOOPCNT_Y = TIMERB_Y+19, + VOLDOWN_Y = LOOPCNT_Y+19, + PGMNUM_Y = VOLDOWN_Y+19, + LOGO_NUM = 1, + LOGO_Y = 1, + LOGO_FM_W = 31, + LOGO_DS_W = 32, + LOGO_P_W = 15, + LOGO_H = 12, + LOGO_FM_X = 312, + LOGO_DS_X = LOGO_FM_X+LOGO_FM_W+2, + LOGO_P_X = LOGO_DS_X+LOGO_DS_W+2, + CIRCLE_W = 31, + CIRCLE_H = 31, + CIRCLE_X = 312, + CIRCLE_Y = 70, + TOP_MUS_X = 397, + TOP_MUSIC_Y = 7, + TOP_IC_X = TOP_MUS_X+14, + TOP_F_X = TOP_IC_X+12, + TOP_ILE_X = TOP_F_X+4, + TOP_SELECTOR_X = TOP_ILE_X+17, + TOP_AND_X = TOP_SELECTOR_X+42, + TOP_STATUS_X = TOP_AND_X+7, + TOP_D_X = TOP_STATUS_X+32, + TOP_ISPLAY_X = TOP_D_X+4, + TOP_VER_X = TOP_ISPLAY_X+32, + TOP_TEXT_W = 231, + TOP_TEXT_H = 5, + TOP_TEXT_Y = TOP_MUSIC_Y-6, + VER_W = 13, + VER_H = 5, + VER_Y = 8, + VER_0_X = TOP_VER_X+15, + VER_1_X = VER_0_X+7, + VER_2_X = VER_1_X+7, + DRIVER_TEXT_X = 312, + DRIVER_TEXT_Y = 27, + DRIVER_TEXT_2_X = DRIVER_TEXT_X+9, + DRIVER_TRI_X = DRIVER_TEXT_2_X+26, + DRIVER_TRI_Y = DRIVER_TEXT_Y+3, + CURL_W = 11, + CURL_H = 11, + CURL_LEFT_X = 347, + CURL_RIGHT_X = 509, + CURL_Y = 80, + PLAY_W = 30, + PLAY_H = 7, + PLAY_X = 354, + PLAY_Y = 77, + STOP_W = 31, + STOP_H = 7, + STOP_X = 393, + STOP_Y = 77, + PAUSE_W = 37, + PAUSE_H = 7, + PAUSE_X = 433, + PAUSE_Y = 77, + FADE_W = 31, + FADE_H = 7, + FADE_X = 481, + FADE_Y = 77, + FF_W = 20, + FF_H = 7, + FF_X = 360, + FF_Y = 87, + REW_W = 26, + REW_H = 7, + REW_X = 392, + REW_Y = 87, + FLOPPY_W = 74, + FLOPPY_H = 7, + FLOPPY_X = 432, + FLOPPY_Y = 87, + LEVEL_TEXT_X = 318, + LEVEL_TEXT_Y = 290, }; enum { @@ -100,6 +199,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 136, 255, 68, 51, 51, 238, 0, 187, 255, + 68, 102, 170, }, { 0, 0, 0, @@ -111,6 +211,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 153, 255, 119, 102, 85, 255, 0, 204, 255, + 85, 119, 170, }, { 0, 0, 0, @@ -122,6 +223,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 255, 221, 85, 255, 102, 0, 255, 85, 0, + 170, 119, 85, }, { 0, 0, 0, @@ -133,6 +235,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 119, 255, 34, 136, 68, 221, 0, 187, 255, + 136, 102, 187, }, { 0, 0, 0, @@ -144,6 +247,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 255, 68, 0, 85, 85, 255, 255, 119, 255, + 119, 119, 187, }, { 0, 0, 0, @@ -155,6 +259,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 255, 221, 0, 255, 0, 51, 255, 0, 51, + 170, 136, 0, }, { 102, 170, 238, @@ -166,6 +271,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 0, 51, 136, 34, 102, 187, 0, 85, 204, + 68, 136, 255, }, { 0, 0, 0, @@ -177,6 +283,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { 85, 255, 68, 34, 17, 255, 0, 170, 255, + 68, 85, 170, }, { LCDB(255), @@ -188,6 +295,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { LCDB(218), LCDB(109), LCDB(218), + LCDB(0), }, { LCD(255), @@ -199,6 +307,7 @@ static const uint8_t s_palettes[PALETTE_NUM][FMDSP_PALETTE_COLORS*3] = { LCD(0), LCD(109), LCD(0), + LCD(0), }, }; @@ -356,6 +465,50 @@ static const uint8_t s_num[11][NUM_W*NUM_H] = { 0, 0, 3, 3, 3, 0, 0, 0, } }; + +static const uint8_t s_num_colon[2][NUM_W*NUM_H] = { + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 2, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 2, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }, + { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 3, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 3, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + }, +}; + +static const uint8_t s_num_bar[NUM_W*NUM_H] = { + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2, 2, 2, 0, 0, 0, +}; + static const uint8_t s_key_bg[KEY_W*KEY_H] = { 4,4,4,0,0,0,4,4,0,0,0,4,4,4,0,4,4,4,0,0,0,4,4,0,0,0,4,4,0,0,0,4,4,4,0, 4,4,4,0,0,0,4,4,0,0,0,4,4,4,0,4,4,4,0,0,0,4,4,0,0,0,4,4,0,0,0,4,4,4,0, @@ -488,3 +641,229 @@ static const uint8_t s_dt_sign[3][DT_SIGN_W*DT_SIGN_H] = { 0, 1, 0, } }; + +static const uint8_t s_logo_fm[LOGO_FM_W*LOGO_H] = { + 0,9,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,9,2,2,2,0,0,0,0,0,2,2,2,9,0, + 9,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,9,2,2,2,2,2,0,0,0,2,2,2,2,2,9, + 2,2,2,9,3,3,3,3,3,3,3,3,3,3,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,2,2,2,2,2,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,2,2,2,0,0,0,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,3,3,3,3,3,3,3,3,3,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, +}; + +static const uint8_t s_logo_ds[LOGO_DS_W*LOGO_H] = { + 2,2,2,2,2,2,2,2,2,2,2,2,9,0,0,0,0,0,9,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,9,2,2,2,2,2,2,2,2,2,2,2,2,2,2, + 2,2,2,3,3,3,3,3,3,3,3,9,2,2,9,0,0,2,2,2,9,3,3,3,3,3,3,3,3,3,3,3, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,2,2,2,9,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,9,2,2,2,2,2,2,2,2,2,2,2,2,9,0, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,9,2,2,2,2,2,2,2,2,2,2,2,2,9, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,3,3,3,3,3,3,3,3,9,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,9,2,2,9,0,0,0,0,0,0,0,0,0,0,0,0,0,9,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,9, + 2,2,2,2,2,2,2,2,2,2,2,2,9,0,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,9,0, +}; + +static const uint8_t s_logo_p[LOGO_P_W*LOGO_H] = { + 2,2,2,2,2,2,2,2,2,2,2,2,2,9,0, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,9, + 2,2,2,3,3,3,3,3,3,3,3,9,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,0,2,2,2, + 2,2,2,0,0,0,0,0,0,0,0,9,2,2,2, + 2,2,2,2,2,2,2,2,2,2,2,2,2,2,9, + 2,2,2,2,2,2,2,2,2,2,2,2,2,9,0, + 2,2,2,3,3,3,3,3,3,3,3,3,3,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, + 2,2,2,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static const uint8_t s_circle[CIRCLE_W*CIRCLE_H] = { + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,8,0,0,0,1,0,1,0,0,0,2,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,8,0,8,0,0,0,1,0,1,0,0,0,2,0,2,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,8,0,0,8,0,0,1,0,1,0,0,2,0,0,2,0,0,0,0,0,0,0,0, + 0,0,0,0,0,7,0,0,0,8,0,8,0,0,1,0,1,0,0,2,0,2,0,0,0,3,0,0,0,0,0, + 0,0,0,0,7,0,7,0,0,8,0,0,8,0,1,0,1,0,2,0,0,2,0,0,3,0,3,0,0,0,0, + 0,0,0,0,0,7,0,7,0,0,8,0,8,0,1,0,1,0,2,0,2,0,0,3,0,3,0,0,0,0,0, + 0,0,0,0,0,0,7,0,7,0,8,0,0,0,0,0,0,0,0,0,2,0,3,0,3,0,0,0,0,0,0, + 0,0,6,6,0,0,0,7,0,7,0,0,0,0,0,0,0,0,0,0,0,3,0,3,0,0,0,4,4,0,0, + 0,0,0,0,6,6,0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,0,3,0,0,4,4,0,0,0,0, + 0,6,6,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,4,4,0, + 0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0, + 0,0,0,0,0,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4,4,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,5,5,5,5,5,5, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0,0,0, + 0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0, + 0,4,4,0,0,0,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6,6,0,0,0,6,6,0, + 0,0,0,0,4,4,0,0,3,0,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,6,6,0,0,0,0, + 0,0,4,4,0,0,0,3,0,3,0,0,0,0,0,0,0,0,0,0,0,7,0,7,0,0,0,6,6,0,0, + 0,0,0,0,0,0,3,0,3,0,2,0,0,0,0,0,0,0,0,0,8,0,7,0,7,0,0,0,0,0,0, + 0,0,0,0,0,3,0,3,0,0,2,0,2,0,1,0,1,0,8,0,8,0,0,7,0,7,0,0,0,0,0, + 0,0,0,0,3,0,3,0,0,2,0,0,2,0,1,0,1,0,8,0,0,8,0,0,7,0,7,0,0,0,0, + 0,0,0,0,0,3,0,0,0,2,0,2,0,0,1,0,1,0,0,8,0,8,0,0,0,7,0,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,0,2,0,0,1,0,1,0,0,8,0,0,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,2,0,2,0,0,0,1,0,1,0,0,0,8,0,8,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,2,0,0,0,1,0,1,0,0,0,8,0,0,0,0,0,0,0,0,0,0, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0, +}; + +static const uint8_t s_text[TOP_TEXT_W*TOP_TEXT_H] = { + 0,0,7,0,0,0,0,0,0,0,0,0,0,0,0,7,0,0,7,0,7,0,0,7,0,7,7,7,0,7,0,0,7,0,0,0,0,0, + 7,0,0,0,0,7,7,7,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,0,0,0,7,7,7,0,7,7,7,7,0,7,0, + 0,7,0,0,0,0,0,0,7,7,7,0,0,0,0,0,7,0,0,7,0,0,7,7,0,0,0,7,7,0,0,0,0,0,0,0,7,7, + 0,0,7,0,0,7,0,7,7,7,0,0,0,7,7,0,0,0,0,7,0,0,0,0,0,0,0,7,7,0,0,7,7,7,0,0,7,0, + 0,7,0,0,0,0,7,0,0,0,0,0,7,0,0,7,0,7,7,7,0,7,0,0,7,0,7,7,7,0,0,0,7,7,0,0,7,0, + 0,7,0,0,7,7,7,0,0,0,0,7,7,0,0,0,7,7,0,0,0,7,7,0,0,0,7,7,0,0,0,0,0,0,7,0,0,0, + 7,7,0,0,7,0,0,0,7,7,0,0,7,0,7,0,0,0,7,0,0,7,0,7,7,0,7,0,0,7,0,0,0,7,7,0,0,0, + 0,7,0,7,0,0,0,0,0,7,0,0,7,7,0,7,0,7,0,0,7,0,0,7,7,0,0,0,0,7,0,0,0,0,0,0,0,0, + 0,7,0,7,0,0,0,7,0,0,0,0,0,0,7,0,0,0,0,0,7,7,0,0,7,0,0,7,0,7,0,0,0,0,0,0,7,0, + 7,0,0,7,0,7,7,7,7,0,7,0,0,7,0,7,0,0,0,0,0,7,7,0,0,0,0,7,0,7,0,0,7,0,7,0,0,7, + 0,7,7,7,7,0,0,0,7,0,7,0,0,0,0,7,0,0,7,0,0,7,0,0,7,7,0,7,0,7,0,0,7,0,7,0,0,7, + 0,7,0,0,7,0,7,0,0,0,0,0,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,0,0,0,7,7, + 0,0,7,0,0,7,7,7,7,0,7,0,0,7,0,7,7,0,0,0,0,7,0,0,7,0,7,0,7,7,0,0,7,0,0,0,0,0, + 0,0,0,7,0,0,7,0,0,0,0,0,7,0,0,7,0,7,7,0,7,0,0,7,0,0,0,0,0,0,0,0,7,0,7,7,0,0, + 7,7,0,0,7,0,0,0,0,7,7,7,0,0,0,7,7,0,0,0,0,0,0,0,0,0,0,0,7,7,0,0,7,7,7,0,0,0, + 7,0,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,7,7,7,0,0,7,0,7,0,0,0,7,0,0,7,0,0,7,0,7, + 0,0,7,0,7,0,0,7,0,0,0,0,7,0,7,0,0,0,7,0,0,7,0,0,7,0,0,7,0,7,7,0,7,0,0,7,0,7, + 0,0,7,0,7,0,0,7,0,0,7,7,0,0,0,0,0,0,7,0,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,7,7, + 0,0,7,0,0,7,0,0,7,0,7,0,0,7,0,0,7,0,7,0,0,0,0,0,7,0,0,7,0,7,0,0,7,0,0,7,0,0, + 0,7,7,0,0,7,0,0,0,7,0,0,0,0,0,7,0,0,7,0,0,7,0,7,0,0,7,0,0,7,7,0,0,0,0,7,0,0, + 7,0,0,7,7,0,0,7,0,7,0,0,0,7,0,0,0,0,0,0,7,0,0,0,0,0,7,7,0,0,7,0,0,7,0,7,0,0, + 7,0,7,0,0,0,7,0,7,7,0,7,0,0,7,0,0,0,0,7,0,7,0,0,7,0,7,7,7,7,0,7,0,0,0,7,0,7, + 7,0,7,0,7,0,0,7,0,0,7,0,0,0,7,0,7,0,0,0,0,7,7,7,7,0,0,7,0,0,7,0,0,7,0,0,0,0, + 7,0,7,0,0,7,0,7,7,7,7,0,0,0,0,7,0,0,0,0,7,0,0,0,7,0,0,7,0,7,0,0,7,0,7,0,0,7, + 0,0,0,0,0,7,0,0,7,0,0,7,0,7,0,0,0,7,7,0,0,7,0,0,0,0,0,0,7,7,0,0,7,0,0,7,0,7, + 7,7,0,7,0,0,7,0,0,0,0,0,0,7,7,7,0,7,7,7,0,7,0,0,7,0,0,7,7,0,0,7,0,0,7,0,0,0, + 0,7,7,7,0,0,7,7,0,0,7,0,0,7,0,0,0,0,0,0,7,7,7,0,0,0,0,0,7,0,0,7,0,0,7,7,0,0, + 0,7,7,0,0,0,0,0,0,7,0,0,7,0,7,0,0,7,0,7,7,7,0,0,0,7,7,0,0,0,0,7,0,0,0,0,0,0, + 7,0,0,7,0,7,0,0,7,0,7,0,0,7,0,0,0,0,7,0,7,0,0,0,7,0,0,7,0,7,7,7,0,7,0,0,7,0, + 7,7,7,0,0,0,7,7,0,0,7,0,0,7,0,7,7,7,0,0,0,0,7,7,7,7,0,0,7,7,0,0,0,7,7,0,0,0, + 7,7,0,0,0,0,0,7,7,7,0,0,7,7,0 +}; + +static const uint8_t s_ver[VER_W*VER_H] = { + 2,0,0,2,0,0,0,0,0,0,0,0,0, + 2,0,0,2,0,0,2,2,0,0,2,0,2, + 2,0,0,2,0,2,2,2,2,0,2,2,0, + 0,2,2,0,0,2,0,0,0,0,2,0,0, + 0,2,2,0,0,0,2,2,2,0,2,0,0, +}; + +static const uint8_t s_curl_left[CURL_W*CURL_H] = { + 0,3,3,3,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 3,0,0,0,0,0,0,0,0,0,0, + 0,3,3,3,3,3,3,3,3,3,3, +}; + +static const uint8_t s_curl_right[CURL_W*CURL_H] = { + 0,0,0,0,0,0,0,3,3,3,0, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 0,0,0,0,0,0,0,0,0,0,3, + 3,3,3,3,3,3,3,3,3,3,0, +}; + +static const uint8_t s_play[PLAY_W*PLAY_H] = { + 1,0,0,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,0,1,1,1,0,0,1,0,0,0,1, + 1,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,1, + 1,1,1,0,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,1,0,1,0, + 1,1,1,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0, + 1,1,1,0,0,0,0,1,1,1,1,0,0,1,0,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0, + 1,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0, + 1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,0,1,0,0,0,1,0,0,0,1,0,0, +}; + +static const uint8_t s_stop[STOP_W*STOP_H] = { + 0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,0,0,1,1,1,0,0,1,1,1,1,0, + 1,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1, + 1,1,1,1,1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1, + 1,1,1,1,1,0,0,0,0,1,1,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,1, + 1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,1,1,1,0, + 1,1,1,1,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,1,0,0,0,0, + 0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0,1,0,0,0,0,1,1,1,0,0,1,0,0,0,0, +}; + +static const uint8_t s_pause[PAUSE_W*PAUSE_H] = { + 0,0,0,0,0,0,0,0,3,3,3,3,0,0,0,3,3,3,0,0,3,0,0,0,3,0,0,3,3,3,3,0,0,3,3,3,3, + 3,3,0,3,3,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,0,0,3,0,0,0,0, + 3,3,0,3,3,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,0,0,3,0,0,0,0, + 3,3,0,3,3,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,3,0,0,3,3,3,0,0,3,3,3,3,0, + 3,3,0,3,3,0,0,0,3,3,3,3,0,0,3,3,3,3,3,0,3,0,0,0,3,0,0,0,0,0,3,0,3,0,0,0,0, + 3,3,0,3,3,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,0,0,0,0,3,0,3,0,0,0,0, + 0,0,0,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,0,3,3,3,0,0,3,3,3,3,0,0,0,3,3,3,3, +}; + +static const uint8_t s_fade[FADE_W*FADE_H] = { + 0,0,0,0,0,0,0,0,0,3,3,3,3,0,0,3,3,3,0,0,3,3,3,3,0,0,0,3,3,3,3, + 3,0,0,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,0, + 3,0,0,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,0, + 3,0,3,0,0,0,0,0,3,3,3,3,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,3,3,3,0, + 3,0,3,0,0,0,0,0,3,0,0,0,0,0,3,3,3,3,3,0,3,0,0,0,3,0,3,0,0,0,0, + 3,0,3,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,3,0,0,0,0, + 3,0,3,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,3,3,3,0,0,0,3,3,3,3, +}; + +static const uint8_t s_ff[FF_W*FF_H] = { + 3,0,0,3,0,0,0,0,0,0,3,3,3,3,0,0,3,3,3,3, + 3,3,0,3,3,0,0,0,0,3,0,0,0,0,0,3,0,0,0,0, + 3,3,0,3,3,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0, + 3,3,0,3,3,3,3,0,0,3,3,3,3,0,0,3,3,3,3,0, + 3,3,0,3,3,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0, + 3,3,0,3,3,0,0,0,0,3,0,0,0,0,0,3,0,0,0,0, + 3,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,0, +}; + +static const uint8_t s_rew[REW_W*REW_H] = { + 0,0,0,3,0,0,3,0,0,3,3,3,3,0,0,0,3,3,3,3,0,3,0,0,0,3, + 0,0,3,3,0,3,3,0,0,3,0,0,0,3,0,3,0,0,0,0,0,3,0,3,0,3, + 0,3,3,3,0,3,3,0,0,3,0,0,0,3,0,3,0,0,0,0,0,3,0,3,0,3, + 3,3,3,3,0,3,3,0,0,3,0,0,3,0,0,3,3,3,3,0,0,3,0,3,0,3, + 0,3,3,3,0,3,3,0,0,3,3,3,0,0,0,3,0,0,0,0,0,3,0,3,0,3, + 0,0,3,3,0,3,3,0,0,3,0,0,3,0,0,3,0,0,0,0,0,3,0,3,0,3, + 0,0,0,3,0,0,3,0,0,3,0,0,0,3,0,0,3,3,3,3,0,0,3,0,3,0, +}; + +static uint8_t s_floppy[FLOPPY_W*FLOPPY_H] = { + 3,3,3,3,3,3,3,0,0,0,3,3,3,3,0,0,3,3,3,0,0,3,0,0,0,0,0,0,3,3,3,3,0,3,3,3,3,0, + 0,0,3,3,3,0,0,3,0,0,0,3,0,0,0,3,0,0,0,0,3,3,3,0,0,0,3,3,3,0,0,0,0,0,3,0,3,3, + 3,3,3,3,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3, + 0,0,0,3,0,3,3,0,3,3,0,0,3,3,0,0,0,3,0,0,0,3,0,3,0,0,0,3,0,0,0,3,3,0,3,3,3,0, + 3,3,3,0,0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0, + 0,0,0,3,0,3,0,3,0,0,0,3,0,0,0,0,0,0,0,3,0,0,0,0,0,3,0,0,3,0,3,0,3,3,0,0,0,3, + 3,0,0,3,3,3,3,0,0,0,0,3,0,0,0,3,0,0,0,0,0,3,3,3,3,0,0,3,0,0,0,3,0,3,0,0,0,0, + 0,3,0,0,0,3,0,0,0,3,0,0,0,0,0,0,3,0,0,0,0,3,3,0,0,3,0,0,3,0,3,3,3,0,3,3,3,0, + 0,3,0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,3,3,3,0,0,3,0,0,0,0,0,3, + 0,0,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,0,0,3,0,3,3,3,3,3,3,3,3,3,3,3,3,0,0,3, + 0,0,0,0,0,0,0,3,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,0,0,3,0,0,0,3,0,3,0,0, + 0,3,0,0,0,3,0,0,0,0,3,0,0,0,0,3,0,0,0,3,0,0,0,0,3,0,3,3,3,3,3,3,3,0,0,3,0,0, + 0,0,0,0,3,3,3,0,0,0,3,3,3,3,0,0,3,3,3,3,0,3,0,0,0,0,0,0,3,3,3,0,0,3,0,0,0,3, + 0,0,3,3,3,0,0,3,3,3,3,3,0,0,3,3,3,0,0,0,0,0,3,0, +}; diff --git a/fmdsp/font_fmdsp_small_data.h b/fmdsp/font_fmdsp_small_data.h index d5f9105..60ee56a 100644 --- a/fmdsp/font_fmdsp_small_data.h +++ b/fmdsp/font_fmdsp_small_data.h @@ -1,5 +1,4 @@ -static const unsigned char fontdat[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +static unsigned char fontdat[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -19,10 +18,11 @@ static const unsigned char fontdat[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x40, 0xa0, 0x50, 0xa0, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0xe0, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x10, 0x20, 0x40, 0x00, 0x00, 0x60, 0x90, 0x90, 0x90, 0x60, 0x00, 0x20, 0x60, 0x20, 0x20, 0x70, 0x00, 0x60, 0x90, 0x20, 0x40, 0xf0, 0x00, 0xe0, 0x10, 0x60, 0x10, 0xe0, 0x00, 0x20, 0x60, 0xa0, 0xf0, 0x20, 0x00, 0xf0, 0x80, 0xe0, 0x10, 0xe0, @@ -49,18 +49,18 @@ static const unsigned char fontdat[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x80, 0xb0, 0x80, 0xf0, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x70, 0x90, 0x80, 0x70, 0x00, 0xf0, 0x80, 0xb0, 0x80, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x90, 0xa0, 0xc0, 0xa0, 0x90, + 0x00, 0x80, 0x80, 0x80, 0x80, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x90, 0x90, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0x20, 0x40, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -128,4 +128,3 @@ static const unsigned char fontdat[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - diff --git a/gtk/Makefile.am b/gtk/Makefile.am index fb06655..8777418 100644 --- a/gtk/Makefile.am +++ b/gtk/Makefile.am @@ -16,7 +16,8 @@ FMDRIVER_SRC=../fmdriver/fmdriver_fmp.c \ FMDSP_SRC=../fmdsp/fmdsp.c \ ../fmdsp/fmdsp-vramlookup-c.c \ ../fmdsp/font_rom.c \ - ../fmdsp/font_fmdsp_small.c + ../fmdsp/font_fmdsp_small.c \ + ../fmdsp/fmdsp_platform_unix.c #fmplayer_CFLAGS=$(CFLAGS) #CFLAGS= @@ -48,6 +49,7 @@ fmplayer_SOURCES=main.c \ ../common/fmplayer_file_gio.c \ ../common/fmplayer_work_opna.c \ ../common/fmplayer_drumrom_unix.c \ + ../fft/fft.c \ $(LIBOPNA_SRC) \ $(FMDRIVER_SRC) \ $(FMDSP_SRC) diff --git a/gtk/fmplayer.xpm b/gtk/fmplayer.xpm index d52d9f4..87ae7a6 100644 --- a/gtk/fmplayer.xpm +++ b/gtk/fmplayer.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char *fmplayer_xpm_16[] = { +static const char *fmplayer_xpm_16[] = { /* columns rows colors chars-per-pixel */ "16 16 4 1 ", " c #40A040", diff --git a/gtk/fmplayer32.xpm b/gtk/fmplayer32.xpm index 062d12e..a97a327 100644 --- a/gtk/fmplayer32.xpm +++ b/gtk/fmplayer32.xpm @@ -1,5 +1,5 @@ /* XPM */ -static char *fmplayer_xpm_32[] = { +static const char *fmplayer_xpm_32[] = { /* columns rows colors chars-per-pixel */ "32 32 8 1 ", " c gray25", @@ -19,6 +19,7 @@ #include "oscilloview.h" #include "wavesave.h" #include "common/fmplayer_common.h" +#include "fft/fft.h" #include "fmplayer.xpm" #include "fmplayer32.xpm" @@ -58,8 +59,12 @@ static struct { const char *current_uri; bool oscillo_should_update; struct oscillodata oscillodata_audiothread[LIBOPNA_OSCILLO_TRACK_COUNT]; + atomic_flag at_fftdata_flag; + struct fmplayer_fft_data at_fftdata; + struct fmplayer_fft_input_data fftdata; } g = { - .oscillo_should_update = true + .oscillo_should_update = true, + .at_fftdata_flag = ATOMIC_FLAG_INIT, }; static void quit(void) { @@ -140,6 +145,11 @@ static int pastream_cb(const void *inptr, void *outptr, unsigned long frames, atomic_flag_clear_explicit(&oscilloview_g.flag, memory_order_release); } } + if (!atomic_flag_test_and_set_explicit( + &g.at_fftdata_flag, memory_order_acquire)) { + fft_write(&g.at_fftdata, buf, frames); + atomic_flag_clear_explicit(&g.at_fftdata_flag, memory_order_release); + } return paContinue; } @@ -228,6 +238,7 @@ static bool openfile(const char *uri) { fmdsp_vram_init(&g.fmdsp, &g.work, g.vram); Pa_StartStream(g.pastream); g.pa_paused = false; + g.work.paused = false; { const char *turi = strdup(uri); free((void *)g.current_uri); @@ -282,7 +293,12 @@ static gboolean draw_cb(GtkWidget *w, gpointer p) { (void)w; (void)p; - fmdsp_update(&g.fmdsp, &g.work, &g.opna, g.vram); + if (!atomic_flag_test_and_set_explicit( + &g.at_fftdata_flag, memory_order_acquire)) { + memcpy(&g.fftdata.fdata, &g.at_fftdata, sizeof(g.fftdata)); + atomic_flag_clear_explicit(&g.at_fftdata_flag, memory_order_release); + } + fmdsp_update(&g.fmdsp, &g.work, &g.opna, g.vram, &g.fftdata); fmdsp_vrampalette(&g.fmdsp, g.vram, g.vram32, g.vram32_stride); cairo_surface_t *s = cairo_image_surface_create_for_data( g.vram32, CAIRO_FORMAT_RGB24, PC98_W, PC98_H, g.vram32_stride); @@ -391,9 +407,11 @@ static gboolean key_press_cb(GtkWidget *w, if (g.pa_paused) { Pa_StartStream(g.pastream); g.pa_paused = false; + g.work.paused = false; } else { Pa_StopStream(g.pastream); g.pa_paused = true; + g.work.paused = true; } break; case GDK_KEY_F11: @@ -481,6 +499,7 @@ int main(int argc, char **argv) { if (__builtin_cpu_supports("sse2")) opna_ssg_sinc_calc_func = opna_ssg_sinc_calc_sse2; if (__builtin_cpu_supports("ssse3")) fmdsp_vramlookup_func = fmdsp_vramlookup_ssse3; #endif + fft_init_table(); load_fontrom(); gtk_init(&argc, &argv); { diff --git a/libopna/opna.c b/libopna/opna.c index 567c913..9f87ff3 100644 --- a/libopna/opna.c +++ b/libopna/opna.c @@ -9,6 +9,7 @@ void opna_reset(struct opna *opna) { opna_drum_reset(&opna->drum); opna_adpcm_reset(&opna->adpcm); opna->mask = 0; + opna->generated_frames = 0; } void opna_writereg(struct opna *opna, unsigned reg, unsigned val) { @@ -42,6 +43,7 @@ void opna_mix_oscillo(struct opna *opna, int16_t *buf, unsigned samples, struct oscillo ? &oscillo[6] : 0, offset); opna_drum_mix(&opna->drum, buf, samples); opna_adpcm_mix(&opna->adpcm, buf, samples); + opna->generated_frames += samples; } unsigned opna_get_mask(const struct opna *opna) { diff --git a/libopna/opna.h b/libopna/opna.h index 2ebca0d..a49a5f8 100644 --- a/libopna/opna.h +++ b/libopna/opna.h @@ -41,6 +41,7 @@ struct opna { struct opna_adpcm adpcm; struct opna_ssg_resampler resampler; unsigned mask; + uint64_t generated_frames; }; void opna_reset(struct opna *opna); diff --git a/win32/amd64/Makefile b/win32/amd64/Makefile index 22ef073..97e46dc 100644 --- a/win32/amd64/Makefile +++ b/win32/amd64/Makefile @@ -4,6 +4,7 @@ vpath %.c ../../libopna vpath %.c ../../fmdsp vpath %.c ../../tonedata vpath %.c ../../common +vpath %.c ../../fft vpath %.rc .. include ../fmplayer.mak diff --git a/win32/fmplayer.mak b/win32/fmplayer.mak index 9a514b2..d62861c 100644 --- a/win32/fmplayer.mak +++ b/win32/fmplayer.mak @@ -21,11 +21,13 @@ LIBOPNA_OBJS=opna \ FMDSP_OBJS=fmdsp \ fmdsp-vramlookup-c \ font_rom \ - font_fmdsp_small + font_fmdsp_small \ + fmdsp_platform_win TONEDATA_OBJS=tonedata SSEOBJBASE=opnassg-sinc-sse2 \ fmdsp-vramlookup-ssse3 OBJBASE=main \ + fft \ toneview \ oscilloview \ wavesave \ diff --git a/win32/main.c b/win32/main.c index 66a1bf0..c1df7a7 100644 --- a/win32/main.c +++ b/win32/main.c @@ -22,6 +22,7 @@ #include "about.h" #include "common/fmplayer_common.h" #include "wavesave.h" +#include "fft/fft.h" enum { ID_OPENFILE = 0x10, @@ -74,7 +75,12 @@ static struct { HBITMAP bitmap_vram; uint8_t *vram32; bool drum_loaded; -} g; + atomic_flag at_fftdata_flag; + struct fmplayer_fft_data at_fftdata; + struct fmplayer_fft_input_data fftdata; +} g = { + .at_fftdata_flag = ATOMIC_FLAG_INIT, +}; HWND g_currentdlg; @@ -92,6 +98,11 @@ static void sound_cb(void *p, int16_t *buf, unsigned frames) { memcpy(oscilloview_g.oscillodata, g.oscillodata_audiothread, sizeof(oscilloview_g.oscillodata)); atomic_flag_clear_explicit(&oscilloview_g.flag, memory_order_release); } + if (!atomic_flag_test_and_set_explicit( + &g.at_fftdata_flag, memory_order_acquire)) { + fft_write(&g.at_fftdata, buf, frames); + atomic_flag_clear_explicit(&g.at_fftdata_flag, memory_order_release); + } } static bool loadfontrom(void) { @@ -170,6 +181,7 @@ static void openfile(HWND hwnd, const wchar_t *path) { if (!g.sound) goto err; g.sound->pause(g.sound, 0); g.paused = false; + g.work.paused = false; wchar_t *pathcpy = HeapAlloc(g.heap, 0, (lstrlen(path)+1)*sizeof(wchar_t)); if (pathcpy) { lstrcpy(pathcpy, path); @@ -333,6 +345,7 @@ static bool proc_key(UINT vk, bool down, int repeat) { case VK_F7: if (g.sound) { g.paused = !g.paused; + g.work.paused = g.paused; g.sound->pause(g.sound, g.paused); } return true; @@ -549,6 +562,7 @@ static void on_command(HWND hwnd, int id, HWND hwnd_c, UINT code) { case ID_PAUSE: if (g.sound) { g.paused = !g.paused; + g.work.paused = g.paused; g.sound->pause(g.sound, g.paused); } break; @@ -611,7 +625,12 @@ static void on_destroy(HWND hwnd) { } static void on_paint(HWND hwnd) { - fmdsp_update(&g.fmdsp, &g.work, &g.opna, g.vram); + if (!atomic_flag_test_and_set_explicit( + &g.at_fftdata_flag, memory_order_acquire)) { + memcpy(&g.fftdata.fdata, &g.at_fftdata, sizeof(g.fftdata)); + atomic_flag_clear_explicit(&g.at_fftdata_flag, memory_order_release); + } + fmdsp_update(&g.fmdsp, &g.work, &g.opna, g.vram, &g.fftdata); fmdsp_vrampalette(&g.fmdsp, g.vram, g.vram32, PC98_W*4); PAINTSTRUCT ps; HDC dc = BeginPaint(hwnd, &ps); @@ -738,6 +757,8 @@ int CALLBACK wWinMain(HINSTANCE hinst, HINSTANCE hpinst, if (__builtin_cpu_supports("sse2")) opna_ssg_sinc_calc_func = opna_ssg_sinc_calc_sse2; if (__builtin_cpu_supports("ssse3")) fmdsp_vramlookup_func = fmdsp_vramlookup_ssse3; + fft_init_table(); + const wchar_t *argfile = 0; { wchar_t *cmdline = GetCommandLine(); diff --git a/win32/wavewrite.c b/win32/wavewrite.c index 7c2d6da..37f6145 100644 --- a/win32/wavewrite.c +++ b/win32/wavewrite.c @@ -3,6 +3,7 @@ #define WIN32_LEAN_AND_MEAN #include <windows.h> #include <stdlib.h> +#include <stdio.h> struct wavefile { HANDLE file; @@ -67,17 +68,16 @@ size_t wavewrite_write(struct wavefile *wavefile, const int16_t *buf, size_t fra } void wavewrite_close(struct wavefile *wavefile) { - LONG fp; uint32_t size; DWORD written; - if ((SetFilePointer(wavefile->file, 40, &fp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || (fp != 40)) { + if (SetFilePointer(wavefile->file, 40, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { goto cleanup; } size = wavefile->written_frames * 4; if (!WriteFile(wavefile->file, &size, sizeof(size), &written, 0) || (written != sizeof(size))) { goto cleanup; } - if ((SetFilePointer(wavefile->file, 4, &fp, FILE_BEGIN) == INVALID_SET_FILE_POINTER) || (fp != 4)) { + if (SetFilePointer(wavefile->file, 4, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) { goto cleanup; } size += 4 + 8 + 16 + 8; diff --git a/win32/x86/Makefile b/win32/x86/Makefile index 6146d28..ea2e16e 100644 --- a/win32/x86/Makefile +++ b/win32/x86/Makefile @@ -4,6 +4,7 @@ vpath %.c ../../libopna vpath %.c ../../fmdsp vpath %.c ../../tonedata vpath %.c ../../common +vpath %.c ../../fft vpath %.rc .. include ../fmplayer.mak |