OSDN Git Service

[VM][General] Merge upstream 2016-03-01. (Pahse 1).
[csp-qt/common_source_project-fm7.git] / source / src / vm / datarec.cpp
1 /*
2         Skelton for retropc emulator
3
4         Author : Takeda.Toshiya
5         Date   : 2006.08.18 -
6
7         [ data recorder ]
8 */
9
10 #include "datarec.h"
11 #include "event.h"
12
13 #define EVENT_SIGNAL    0
14 #define EVENT_SOUND     1
15
16 #ifndef DATAREC_FF_REW_SPEED
17 #define DATAREC_FF_REW_SPEED    10
18 #endif
19
20 void DATAREC::initialize()
21 {
22         play_fio = new FILEIO();
23         rec_fio = new FILEIO();
24         
25         memset(rec_file_path, sizeof(rec_file_path), 1);
26         play = rec = remote = trigger = false;
27         ff_rew = 0;
28         in_signal = out_signal = false;
29         register_id = -1;
30         
31         buffer = buffer_bak = NULL;
32 #ifdef DATAREC_SOUND
33         sound_buffer = NULL;
34 #endif
35         apss_buffer = NULL;
36         buffer_ptr = buffer_length = 0;
37         is_wav = is_tap = false;
38         
39         pcm_changed = 0;
40         pcm_last_vol_l = pcm_last_vol_r = 0;
41         
42         // skip frames
43         signal_changed = 0;
44         register_frame_event(this);
45 }
46
47 void DATAREC::reset()
48 {
49         close_tape();
50         pcm_prev_clock = get_current_clock();
51         pcm_positive_clocks = pcm_negative_clocks = 0;
52 }
53
54 void DATAREC::release()
55 {
56         close_file();
57         delete play_fio;
58         delete rec_fio;
59 }
60
61 void DATAREC::write_signal(int id, uint32_t data, uint32_t mask)
62 {
63         bool signal = ((data & mask) != 0);
64         
65         if(id == SIG_DATAREC_MIC) {
66                 if(out_signal != signal) {
67                         if(rec && remote) {
68                                 if(out_signal) {
69                                         pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
70                                 } else {
71                                         pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
72                                 }
73                                 pcm_prev_clock = get_current_clock();
74                                 pcm_changed = 2;
75                                 signal_changed++;
76                         }
77                         if(prev_clock != 0) {
78                                 if(out_signal) {
79                                         positive_clocks += get_passed_clock(prev_clock);
80                                 } else {
81                                         negative_clocks += get_passed_clock(prev_clock);
82                                 }
83                                 prev_clock = get_current_clock();
84                         }
85                         out_signal = signal;
86                 }
87         } else if(id == SIG_DATAREC_REMOTE) {
88                 set_remote(signal);
89         } else if(id == SIG_DATAREC_TRIG) {
90                 // L->H: remote signal is switched
91                 if(signal && !trigger) {
92                         set_remote(!remote);
93                 }
94                 trigger = signal;
95         }
96 }
97
98 void DATAREC::event_frame()
99 {
100         if(pcm_changed) {
101                 pcm_changed--;
102         }
103         if(signal_changed > 10 && ff_rew == 0 && !config.tape_sound) {
104                 request_skip_frames();
105         }
106         signal_changed = 0;
107 }
108
109 void DATAREC::event_callback(int event_id, int err)
110 {
111         if(event_id == EVENT_SIGNAL) {
112                 if(play) {
113                         if(ff_rew > 0) {
114                                 emu->out_message(_T("CMT: Fast Forward (%d %%)"), get_tape_position());
115                         } else if(ff_rew < 0) {
116                                 emu->out_message(_T("CMT: Fast Rewind (%d %%)"), get_tape_position());
117                         } else {
118                                 emu->out_message(_T("CMT: Play (%d %%)"), get_tape_position());
119                         }
120                         bool signal = in_signal;
121                         if(is_wav) {
122                                 if(buffer_ptr >= 0 && buffer_ptr < buffer_length) {
123                                         signal = ((buffer[buffer_ptr] & 0x80) != 0);
124 #ifdef DATAREC_SOUND
125                                         if(sound_buffer != NULL && ff_rew == 0) {
126                                                 sound_sample = sound_buffer[buffer_ptr];
127                                         } else {
128                                                 sound_sample = 0;
129                                         }
130 #endif
131                                 }
132                                 if(ff_rew < 0) {
133                                         if((buffer_ptr = max(buffer_ptr - 1, 0)) == 0) {
134                                                 set_remote(false);      // top of tape
135                                                 signal = false;
136                                         }
137                                 } else {
138                                         if((buffer_ptr = min(buffer_ptr + 1, buffer_length)) == buffer_length) {
139                                                 set_remote(false);      // end of tape
140                                                 signal = false;
141                                         }
142                                 }
143                                 update_event();
144                         } else {
145                                 if(ff_rew < 0) {
146                                         if(buffer_bak != NULL) {
147                                                 memcpy(buffer, buffer_bak, buffer_length);
148                                         }
149                                         buffer_ptr = 0;
150                                         set_remote(false);      // top of tape
151                                 } else {
152                                         while(buffer_ptr < buffer_length) {
153                                                 if((buffer[buffer_ptr] & 0x7f) == 0) {
154                                                         if(++buffer_ptr == buffer_length) {
155                                                                 set_remote(false);      // end of tape
156                                                                 signal = false;
157                                                                 break;
158                                                         }
159                                                         signal = ((buffer[buffer_ptr] & 0x80) != 0);
160                                                 } else {
161                                                         signal = ((buffer[buffer_ptr] & 0x80) != 0);
162                                                         uint8_t tmp = buffer[buffer_ptr];
163                                                         buffer[buffer_ptr] = (tmp & 0x80) | ((tmp & 0x7f) - 1);
164                                                         break;
165                                                 }
166                                         }
167                                 }
168                         }
169                         // notify the signal is changed
170                         if(signal != in_signal) {
171                                 if(in_signal) {
172                                         pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
173                                 } else {
174                                         pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
175                                 }
176                                 pcm_prev_clock = get_current_clock();
177                                 pcm_changed = 2;
178                                 in_signal = signal;
179                                 signal_changed++;
180                                 write_signals(&outputs_ear, in_signal ? 0xffffffff : 0);
181                         }
182                         // chek apss state
183                         if(apss_buffer != NULL) {
184                                 int ptr = (apss_ptr++) % (sample_rate * 2);
185                                 if(apss_buffer[ptr]) {
186                                         apss_count--;
187                                 }
188                                 if(in_signal) {
189                                         apss_count++;
190                                 }
191                                 apss_buffer[ptr] = in_signal;
192                                 
193                                 if(apss_ptr >= sample_rate * 2) {
194                                         double rate = (double)apss_count / (double)(sample_rate * 2);
195                                         if(rate > 0.9 || rate < 0.1) {
196                                                 if(apss_signals) {
197                                                         if(apss_remain > 0) {
198                                                                 apss_remain--;
199                                                         } else if(apss_remain < 0) {
200                                                                 apss_remain++;
201                                                         }
202                                                         write_signals(&outputs_apss, 0xffffffff);
203                                                         apss_signals = false;
204                                                 }
205                                         } else {
206                                                 if(!apss_signals) {
207                                                         write_signals(&outputs_apss, 0);
208                                                         apss_signals = true;
209                                                 }
210                                         }
211                                 }
212                         }
213                 } else if(rec) {
214                         if(out_signal) {
215                                 positive_clocks += get_passed_clock(prev_clock);
216                         } else {
217                                 negative_clocks += get_passed_clock(prev_clock);
218                         }
219                         if(is_wav) {
220                                 if(positive_clocks != 0 || negative_clocks != 0) {
221                                         buffer[buffer_ptr] = (255 * positive_clocks) / (positive_clocks + negative_clocks);
222                                 } else {
223                                         buffer[buffer_ptr] = 0;
224                                 }
225                                 if(++buffer_ptr >= buffer_length) {
226                                         if(is_tap) {
227                                                 for(int i = 0; i < buffer_length; i += 8) {
228                                                         uint8_t val = 0;
229                                                         for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
230                                                                 if(i + j < buffer_length && buffer[i + j] >= 0x80) {
231                                                                         val |= bit;
232                                                                 }
233                                                         }
234                                                         rec_fio->FputUint8(val);
235                                                 }
236                                         } else {
237                                                 rec_fio->Fwrite(buffer, buffer_length, 1);
238                                         }
239                                         buffer_ptr = 0;
240                                 }
241                         } else {
242                                 bool prev_signal = ((buffer[buffer_ptr] & 0x80) != 0);
243                                 bool cur_signal = (positive_clocks > negative_clocks);
244                                 if(prev_signal != cur_signal || (buffer[buffer_ptr] & 0x7f) == 0x7f) {
245                                         if(++buffer_ptr >= buffer_length) {
246                                                 rec_fio->Fwrite(buffer, buffer_length, 1);
247                                                 buffer_ptr = 0;
248                                         }
249                                         buffer[buffer_ptr] = cur_signal ? 0x80 : 0;
250                                 }
251                                 buffer[buffer_ptr]++;
252                         }
253                         prev_clock = get_current_clock();
254                         positive_clocks = negative_clocks = 0;
255                 }
256         }
257 }
258
259 void DATAREC::set_remote(bool value)
260 {
261         if(remote != value) {
262                 remote = value;
263                 update_event();
264         }
265 }
266
267 void DATAREC::set_ff_rew(int value)
268 {
269         if(ff_rew != value) {
270                 if(register_id != -1) {
271                         cancel_event(this, register_id);
272                         register_id = -1;
273                 }
274                 ff_rew = value;
275                 apss_signals = false;
276                 update_event();
277         }
278 }
279
280 bool DATAREC::do_apss(int value)
281 {
282         bool result = false;
283         
284         if(play) {
285                 set_ff_rew(0);
286                 set_remote(true);
287                 set_ff_rew(value > 0 ? 1 : -1);
288                 apss_remain = value;
289                 
290                 while(apss_remain != 0 && remote) {
291                         event_callback(EVENT_SIGNAL, 0);
292                 }
293                 result = (apss_remain == 0);
294         }
295         
296         // stop cmt
297         set_remote(false);
298         set_ff_rew(0);
299         
300         if(value > 0) {
301                 if(play) {
302                         emu->out_message(_T("CMT: APSS Forward (%d %%)"), get_tape_position());
303                 } else {
304                         emu->out_message(_T("CMT: APSS Forward"));
305                 }
306         } else {
307                 if(play) {
308                         emu->out_message(_T("CMT: APSS Rewind (%d %%)"), get_tape_position());
309                 } else {
310                         emu->out_message(_T("CMT: APSS Rewind"));
311                 }
312         }
313         return result;
314 }
315
316 void DATAREC::update_event()
317 {
318         if(remote && (play || rec)) {
319                 if(register_id == -1) {
320                         if(ff_rew != 0) {
321                                 register_event(this, EVENT_SIGNAL, sample_usec / DATAREC_FF_REW_SPEED, true, &register_id);
322                         } else {
323                                 if(rec) {
324                                         emu->out_message(_T("CMT: Record"));
325                                 }
326                                 // ToDo sample_usec -> sample_usec * 2
327                                 register_event(this, EVENT_SIGNAL, sample_usec, true, &register_id);
328                         }
329                         prev_clock = get_current_clock();
330                         positive_clocks = negative_clocks = 0;
331                 }
332         } else {
333                 if(register_id != -1) {
334                         cancel_event(this, register_id);
335                         register_id = -1;
336                         if(play) {
337                                 if(buffer_ptr >= buffer_length) {
338                                         emu->out_message(_T("CMT: Stop (End-of-Tape)"));
339                                 } else if(buffer_ptr <= 0) {
340                                         emu->out_message(_T("CMT: Stop (Beginning-of-Tape)"));
341                                 } else {
342                                         emu->out_message(_T("CMT: Stop (%d %%)"), get_tape_position());
343                                 }
344                         } else {
345                                 emu->out_message(_T("CMT: Stop"));
346                         }
347                 }
348                 prev_clock = 0;
349         }
350         
351         // update signals
352 #ifdef DATAREC_SOUND
353         if(!(play && remote)) {
354                 sound_sample = 0;
355         }
356 #endif
357         write_signals(&outputs_remote, remote ? 0xffffffff : 0);
358         write_signals(&outputs_rotate, (register_id != -1) ? 0xffffffff : 0);
359         write_signals(&outputs_end, (buffer_ptr == buffer_length) ? 0xffffffff : 0);
360         write_signals(&outputs_top, (buffer_ptr == 0) ? 0xffffffff : 0);
361 }
362
363 bool DATAREC::play_tape(const _TCHAR* file_path)
364 {
365         close_tape();
366         
367         if(play_fio->Fopen(file_path, FILEIO_READ_BINARY)) {
368                 if(check_file_extension(file_path, _T(".wav")) || check_file_extension(file_path, _T(".mti"))) {
369                         // standard PCM wave file
370                         if((buffer_length = load_wav_image(0)) != 0) {
371                                 play = is_wav = true;
372                         }
373                 } else if(check_file_extension(file_path, _T(".t77"))) {
374                         // FUJITSU FM-7 series tape image
375                         if((buffer_length = load_t77_image()) != 0) {
376                                 buffer = (uint8_t *)malloc(buffer_length);
377                                 load_t77_image();
378                                 play = is_wav = true;
379                         }
380                 } else if(check_file_extension(file_path, _T(".tap"))) {
381                         // SHARP X1 series tape image
382                         if((buffer_length = load_tap_image()) != 0) {
383                                 buffer = (uint8_t *)malloc(buffer_length);
384                                 load_tap_image();
385                                 play = is_wav = true;
386                         }
387                 } else if(check_file_extension(file_path, _T(".mzt")) || check_file_extension(file_path, _T(".mzf")) || check_file_extension(file_path, _T(".m12"))) {
388                         // SHARP MZ series tape image
389                         if((buffer_length = load_mzt_image()) != 0) {
390                                 buffer = (uint8_t *)malloc(buffer_length);
391                                 load_mzt_image();
392                                 play = is_wav = true;
393                         }
394                 } else if(check_file_extension(file_path, _T(".mtw"))) {
395                         // skip mzt image
396                         uint8_t header[128];
397                         play_fio->Fread(header, sizeof(header), 1);
398                         uint16_t size = header[0x12] | (header[0x13] << 8);
399                         // load standard PCM wave file
400                         if((buffer_length = load_wav_image(sizeof(header) + size)) != 0) {
401                                 play = is_wav = true;
402                         }
403                 } else if(check_file_extension(file_path, _T(".p6"))) {
404                         // NEC PC-6001/6601 series tape image
405                         if((buffer_length = load_p6_image(false)) != 0) {
406                                 buffer = (uint8_t *)malloc(buffer_length);
407                                 load_p6_image(false);
408                                 play = is_wav = true;
409                         }
410                 } else if(check_file_extension(file_path, _T(".p6t"))) {
411                         // NEC PC-6001/6601 series tape image
412                         if((buffer_length = load_p6_image(true)) != 0) {
413                                 buffer = (uint8_t *)malloc(buffer_length);
414                                 load_p6_image(true);
415                                 play = is_wav = true;
416                         }
417                 } else if(check_file_extension(file_path, _T(".cas"))) {
418                         // standard cas image for my emulator
419                         if((buffer_length = load_cas_image()) != 0) {
420                                 buffer = (uint8_t *)malloc(buffer_length);
421                                 load_cas_image();
422                                 play = is_wav = true;
423                         }
424                 }
425                 play_fio->Fclose();
426         }
427         if(play) {
428                 if(!is_wav && buffer_length != 0) {
429                         buffer_bak = (uint8_t *)malloc(buffer_length);
430                         memcpy(buffer_bak, buffer, buffer_length);
431                 }
432                 
433                 // get the first signal
434                 bool signal = ((buffer[0] & 0x80) != 0);
435                 if(signal != in_signal) {
436                         write_signals(&outputs_ear, signal ? 0xffffffff : 0);
437                         in_signal = signal;
438                 }
439                 
440                 // initialize apss
441                 apss_buffer_length = sample_rate * 2;
442                 apss_buffer = (bool *)calloc(apss_buffer_length, 1);
443                 apss_ptr = apss_count = 0;
444                 apss_signals = false;
445                 write_signals(&outputs_apss, 0);
446                 
447                 update_event();
448         }
449         return play;
450 }
451
452 bool DATAREC::rec_tape(const _TCHAR* file_path)
453 {
454         close_tape();
455         
456         if(rec_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
457                 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
458                 sample_rate = 48000;
459                 sample_usec = 1000000. / sample_rate;
460                 buffer_length = 1024 * 1024;
461                 buffer = (uint8_t *)malloc(buffer_length);
462                 
463                 if(check_file_extension(file_path, _T(".wav"))) {
464                         // write wave header
465                         uint8_t dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
466                         memset(dummy, 0, sizeof(dummy));
467                         rec_fio->Fwrite(dummy, sizeof(dummy), 1);
468                         is_wav = true;
469                 } else if(check_file_extension(file_path, _T(".tap"))) {
470                         // write frequency
471                         rec_fio->FputUint32((uint32_t)sample_rate);
472                         is_wav = is_tap = true;
473                 } else {
474                         // initialize buffer
475                         buffer[0] = out_signal ? 0x80 : 0;
476                 }
477                 rec = true;
478                 update_event();
479         }
480         return rec;
481 }
482
483 void DATAREC::close_tape()
484 {
485         close_file();
486         
487         play = rec = is_wav = is_tap = false;
488         buffer_ptr = buffer_length = 0;
489         update_event();
490         
491         // no sounds
492         write_signals(&outputs_ear, 0);
493         in_signal = false;
494 }
495
496 void DATAREC::close_file()
497 {
498         if(play_fio->IsOpened()) {
499                 play_fio->Fclose();
500         }
501         if(rec_fio->IsOpened()) {
502                 if(rec) {
503                         if(is_tap) {
504                                 for(int i = 0; i < buffer_ptr; i += 8) {
505                                         uint8_t val = 0;
506                                         for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
507                                                 if(i + j < buffer_ptr && buffer[i + j] >= 0x80) {
508                                                         val |= bit;
509                                                 }
510                                         }
511                                         rec_fio->FputUint8(val);
512                                 }
513                         } else if(is_wav) {
514                                 save_wav_image();
515                         } else {
516                                 rec_fio->Fwrite(buffer, buffer_ptr + 1, 1);
517                         }
518                 }
519                 rec_fio->Fclose();
520         }
521         if(buffer != NULL) {
522                 free(buffer);
523                 buffer = NULL;
524         }
525         if(buffer_bak != NULL) {
526                 free(buffer_bak);
527                 buffer_bak = NULL;
528         }
529 #ifdef DATAREC_SOUND
530         if(sound_buffer != NULL) {
531                 free(sound_buffer);
532                 sound_buffer = NULL;
533         }
534 #endif
535         if(apss_buffer != NULL) {
536                 free(apss_buffer);
537                 apss_buffer = NULL;
538         }
539 }
540
541 // standard PCM wave file
542
543 int DATAREC::load_wav_image(int offset)
544 {
545         // check wave header
546         wav_header_t header;
547         wav_chunk_t chunk;
548         
549         play_fio->Fseek(offset, FILEIO_SEEK_SET);
550         play_fio->Fread(&header, sizeof(header), 1);
551         if(header.format_id != 1 || !(header.sample_bits == 8 || header.sample_bits == 16)) {
552                 return 0;
553         }
554         play_fio->Fseek(header.fmt_chunk.size - 16, FILEIO_SEEK_CUR);
555         while(1) {
556                 play_fio->Fread(&chunk, sizeof(chunk), 1);
557                 if(strncmp(chunk.id, "data", 4) == 0) {
558                         break;
559                 }
560                 play_fio->Fseek(chunk.size, FILEIO_SEEK_CUR);
561         }
562         
563         int samples = chunk.size / header.channels, loaded_samples = 0;
564         if(header.sample_bits == 16) {
565                 samples /= 2;
566         }
567         sample_rate = header.sample_rate;
568         sample_usec = 1000000. / sample_rate;
569         
570         // load samples
571         if(samples > 0) {
572                 #define TMP_LENGTH (0x10000 * header.channels)
573                 
574                 uint8_t *tmp_buffer = (uint8_t *)malloc(TMP_LENGTH);
575                 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1);
576                 
577                 #define GET_SAMPLE { \
578                         for(int ch = 0; ch < header.channels; ch++) { \
579                                 if(header.sample_bits == 16) { \
580                                         union { \
581                                                 int16_t s16; \
582                                                 struct { \
583                                                         uint8_t l, h; \
584                                                 } b; \
585                                         } pair; \
586                                         pair.b.l = tmp_buffer[tmp_ptr++]; \
587                                         pair.b.h = tmp_buffer[tmp_ptr++]; \
588                                         sample[ch] = pair.s16; \
589                                 } else { \
590                                         sample[ch] = (tmp_buffer[tmp_ptr++] - 128) * 256; \
591                                 } \
592                         } \
593                         if(tmp_ptr == TMP_LENGTH) { \
594                                 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1); \
595                                 tmp_ptr = 0; \
596                         } \
597                 }
598                 
599 #ifdef DATAREC_SOUND
600                 if(!config.wave_shaper || header.channels > 1) {
601 #else
602                 if(!config.wave_shaper) {
603 #endif
604                         buffer = (uint8_t *)malloc(samples);
605 #ifdef DATAREC_SOUND
606                         if(header.channels > 1) {
607                                 sound_buffer_length = samples * sizeof(int16_t);
608                                 sound_buffer = (int16_t *)malloc(sound_buffer_length);
609                         }
610 #endif
611                         bool prev_signal = false;
612                         for(int i = 0, tmp_ptr = 0; i < samples; i++) {
613                                 int16_t sample[16];
614                                 GET_SAMPLE
615                                 bool signal = (sample[0] > (prev_signal ? -1024 : 1024));
616                                 buffer[i] = (signal ? 0xff : 0);
617 #ifdef DATAREC_SOUND
618                                 if(header.channels > 1) {
619                                         sound_buffer[i] = sample[1];
620                                 }
621 #endif
622                                 prev_signal = signal;
623                         }
624                         loaded_samples = samples;
625                 } else {
626                         // load samples
627                         int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
628                         for(int i = 0, tmp_ptr = 0; i < samples; i++) {
629                                 int16_t sample[16];
630                                 GET_SAMPLE
631                                 wav_buffer[i] = sample[0];
632                         }
633                         
634                         // adjust zero position
635                         int16_t *zero_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
636                         int width = (int)(header.sample_rate / 1000.0 + 0.5);
637                         for(int i = width; i < samples - width; i++) {
638                                 int max_sample = -65536, min_sample = 65536;
639                                 for(int j = -width; j < width; j++) {
640                                         if(max_sample < wav_buffer[i + j]) max_sample = wav_buffer[i + j];
641                                         if(min_sample > wav_buffer[i + j]) min_sample = wav_buffer[i + j];
642                                 }
643                                 if(max_sample - min_sample > 4096) {
644                                         zero_buffer[i] = (max_sample + min_sample) / 2;
645                                 } else {
646                                         zero_buffer[i] = wav_buffer[i];
647                                 }
648                         }
649                         for(int i = 0; i < samples; i++) {
650                                 wav_buffer[i] -= zero_buffer[(i < width) ?  width : (i < samples - width) ? i : (samples - width - 1)];
651                         }
652                         free(zero_buffer);
653                         
654                         // t=0 : get thresholds
655                         // t=1 : get number of samples
656                         // t=2 : load samples
657                         #define FREQ_SCALE 16
658                         int min_threshold = (int)(header.sample_rate * FREQ_SCALE / 2400.0 / 2.0 / 3.0 + 0.5);
659                         int max_threshold = (int)(header.sample_rate * FREQ_SCALE / 1200.0 / 2.0 * 3.0 + 0.5);
660                         int half_threshold, hi_count, lo_count;
661                         int *counts = (int *)calloc(max_threshold, sizeof(int));
662                         
663                         for(int t = 0; t < 3; t++) {
664                                 int count_positive = 0, count_negative = 0;
665                                 bool prev_signal = false;
666                                 
667                                 for(int i = 0; i < samples - 1; i++) {
668                                         int prev = wav_buffer[i], next = wav_buffer[i + 1];
669                                         double diff = (double)(next - prev) / FREQ_SCALE;
670                                         for(int j = 0; j < FREQ_SCALE; j++) {
671                                                 int sample = prev + (int)(diff * j + 0.5);
672                                                 bool signal = (sample > 0);
673                                                 
674                                                 if(!prev_signal && signal) {
675                                                         if(t == 0) {
676                                                                 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
677                                                                         counts[count_positive]++;
678                                                                 }
679                                                         } else {
680                                                                 int count_p = count_positive / FREQ_SCALE;
681                                                                 int count_n = count_negative / FREQ_SCALE;
682                                                                 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
683                                                                         count_p = (count_positive > half_threshold) ? hi_count : lo_count;
684                                                                         if(count_negative < max_threshold) {
685                                                                                 count_n = count_p;
686                                                                         }
687                                                                 }
688                                                                 if(buffer != NULL) {
689
690                                                                         for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
691                                                                         for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
692                                                                 } else {
693                                                                         loaded_samples += count_p + count_n;
694                                                                 }
695                                                         }
696                                                         count_positive = count_negative = 0;
697                                                 }
698                                                 if(signal) {
699                                                         count_positive++;
700                                                 } else {
701                                                         count_negative++;
702                                                 }
703                                                 prev_signal = signal;
704                                         }
705                                 }
706                                 if(t == 0) {
707                                         long sum_value = 0, sum_count = 0, half_tmp;
708                                         for(int i = 0; i < max_threshold; i++) {
709                                                 sum_value += i * counts[i];
710                                                 sum_count += counts[i];
711                                         }
712                                         // 1920 = 2400 * 0.6 + 1200 * 0.4
713                                         if(sum_count > 60 * 1920) {
714                                                 half_tmp = (int)((double)sum_value / (double)sum_count + 0.5);
715                                         } else {
716                                                 half_tmp = (int)(header.sample_rate * FREQ_SCALE / 1920.0 / 2.0 + 0.5);
717                                         }
718                                         
719                                         sum_value = sum_count = 0;
720                                         for(int i = 0; i < half_tmp; i++) {
721                                                 sum_value += i * counts[i];
722                                                 sum_count += counts[i];
723                                         }
724                                         double lo_tmp = (double)sum_value / (double)sum_count;
725                                         
726                                         sum_value = sum_count = 0;
727                                         for(int i = half_tmp; i < half_tmp * 2; i++) {
728                                                 sum_value += i * counts[i];
729                                                 sum_count += counts[i];
730                                         }
731                                         double hi_tmp = (double)sum_value / (double)sum_count;
732                                         
733                                         half_threshold = (int)((lo_tmp + hi_tmp) / 2 + 0.5);
734                                         min_threshold = (int)(2 * lo_tmp - half_threshold + 0.5);
735                                         max_threshold = (int)(2 * hi_tmp - half_threshold + 0.5);
736                                         lo_count = (int)(lo_tmp / FREQ_SCALE + 0.5);
737                                         hi_count = (int)(hi_tmp / FREQ_SCALE + 0.5);
738                                 } else {
739                                         int count_p = count_positive / FREQ_SCALE;
740                                         int count_n = count_negative / FREQ_SCALE;
741                                         if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
742                                                 count_p = (count_positive > half_threshold) ? hi_count : lo_count;
743                                                 if(count_negative < max_threshold) {
744                                                         count_n = count_p;
745                                                 }
746                                         }
747                                         if(buffer != NULL) {
748                                                 for(int j = 0; j < count_p; j++) buffer[loaded_samples++] = 0xff;
749                                                 for(int j = 0; j < count_n; j++) buffer[loaded_samples++] = 0x00;
750                                         } else {
751                                                 loaded_samples += count_p + count_n;
752                                         }
753                                 }
754                                 if(t == 1) {
755                                         buffer = (uint8_t *)malloc(loaded_samples);
756 #ifdef DATAREC_SOUND
757                                         if(header.channels > 1) {
758                                                 sound_buffer_length = loaded_samples * sizeof(int16_t);
759                                                 sound_buffer = (int16_t *)malloc(sound_buffer_length);
760                                         }
761 #endif
762                                         loaded_samples = 0;
763                                 }
764                         }
765                         free(counts);
766                         free(wav_buffer);
767                 }
768                 free(tmp_buffer);
769         }
770         return loaded_samples;
771 }
772
773 void DATAREC::save_wav_image()
774 {
775         // write samples remained in buffer
776         if(buffer_ptr > 0) {
777                 rec_fio->Fwrite(buffer, buffer_ptr, 1);
778         }
779         uint32_t length = rec_fio->Ftell();
780         
781         wav_header_t wav_header;
782         wav_chunk_t wav_chunk;
783         
784         memcpy(wav_header.riff_chunk.id, "RIFF", 4);
785         wav_header.riff_chunk.size = length - 8;
786         memcpy(wav_header.wave, "WAVE", 4);
787         memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
788         wav_header.fmt_chunk.size = 16;
789         wav_header.format_id = 1;
790         wav_header.channels = 1;
791         wav_header.sample_rate = sample_rate;
792         wav_header.data_speed = sample_rate;
793         wav_header.block_size = 1;
794         wav_header.sample_bits = 8;
795         
796         memcpy(wav_chunk.id, "data", 4);
797         wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);
798         
799         rec_fio->Fseek(0, FILEIO_SEEK_SET);
800         rec_fio->Fwrite(&wav_header, sizeof(wav_header), 1);
801         rec_fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
802 }
803
804 // FUJITSU FM-7 series tape image
805
806 #define T77_PUT_SIGNAL(signal, len) { \
807         int remain = len; \
808         while(remain > 0) { \
809                 if(buffer != NULL) { \
810                         buffer[ptr++] = (signal) ? 0xff : 0x7f; \
811                 } else { \
812                         ptr++; \
813                 } \
814                 remain--; \
815         } \
816 }
817
818 int DATAREC::load_t77_image()
819 {
820         sample_usec = 9;
821         sample_rate = (int)(1000000.0 / sample_usec + 0.5);
822         
823         // load t77 file
824         uint8_t tmpbuf[17];
825         int ptr = 0;
826         int file_size = (int)play_fio->FileLength();
827         
828         if(file_size <= 0) {
829                 return 0; // over 2GB
830         }
831         play_fio->Fseek(0, FILEIO_SEEK_SET);
832         play_fio->Fread(tmpbuf, 16, 1);
833         tmpbuf[16] = '\0';
834         if(strcmp((char *)tmpbuf, "XM7 TAPE IMAGE 0") != 0) {
835                 return 0;
836         }
837         file_size -= 16;
838         
839         while(file_size > 0) {
840                 uint16_t h = play_fio->FgetUint8();
841                 uint16_t l = play_fio->FgetUint8();
842                 uint16_t v = h * 256 + l;
843                 
844                 if((file_size -= 2) < 0) {
845                         break;
846                 }
847                 if(v & 0x7fff) {
848                         T77_PUT_SIGNAL((h & 0x80) != 0, v & 0x7fff);
849                 }
850         }
851         return ptr;
852 }
853
854 // SHARP X1 series tape image
855
856 /*
857         new tape file format for t-tune (from tape_fmt.txt)
858
859         offset:size :
860         00H   :  4  : \8e¯\95Ê\83C\83\93\83f\83b\83N\83X "TAPE"
861         04H   : 17  : \83e\81[\83v\82Ì\96¼\91O(asciiz)
862         15H   :  5  : \83\8a\83U\81[\83u
863         1AH   :  1  : \83\89\83C\83g\83v\83\8d\83e\83N\83g\83m\83b\83`(00H=\8f\91\82«\8d\9e\82Ý\89Â\81A10H=\8f\91\82«\8d\9e\82Ý\8bÖ\8e~\81j
864         1BH   :  1  : \8bL\98^\83t\83H\81[\83}\83b\83g\82Ì\8eí\97Þ(01H=\92è\91¬\83T\83\93\83v\83\8a\83\93\83O\95û\96@\81j
865         1CH   :  4  : \83T\83\93\83v\83\8a\83\93\83O\8eü\94g\90\94(\82g\82\9a\92P\88Ê\81j
866         20H   :  4  : \83e\81[\83v\83f\81[\83^\82Ì\83T\83C\83Y\81i\83r\83b\83g\92P\88Ê\81j
867         24H   :  4  : \83e\81[\83v\82Ì\88Ê\92u\81i\83r\83b\83g\92P\88Ê\81j
868         28H   :  ?  : \83e\81[\83v\82Ì\83f\81[\83^
869 */
870
871 int DATAREC::load_tap_image()
872 {
873         // get file size
874         play_fio->Fseek(0, FILEIO_SEEK_END);
875         int file_size = play_fio->Ftell();
876         play_fio->Fseek(0, FILEIO_SEEK_SET);
877         
878         // check header
879         uint8_t header[4];
880         play_fio->Fread(header, 4, 1);
881         
882         if(header[0] == 'T' && header[1] == 'A' && header[2] == 'P' && header[3] == 'E') {
883                 // skip name, reserved, write protect notch
884                 play_fio->Fseek(17 + 5 + 1, FILEIO_SEEK_CUR);
885                 // format
886                 if(play_fio->Fgetc() != 0x01) {
887                         // unknown data format
888                         return 0;
889                 }
890                 // sample rate
891                 play_fio->Fread(header, 4, 1);
892                 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
893                 sample_usec = 1000000. / sample_rate;
894                 // data length
895                 play_fio->Fread(header, 4, 1);
896                 // play position
897                 play_fio->Fread(header, 4, 1);
898         } else {
899                 // sample rate
900                 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
901                 sample_usec = 1000000. / sample_rate;
902         }
903         
904         // load samples
905         int ptr = 0, data;
906         while((data = play_fio->Fgetc()) != EOF) {
907                 for(int i = 0, bit = 0x80; i < 8; i++, bit >>= 1) {
908                         if(buffer != NULL) {
909                                 buffer[ptr] = ((data & bit) != 0) ? 255 : 0;
910                         }
911                         ptr++;
912                 }
913         }
914         return ptr;
915 }
916
917 // SHARP MZ series tape image
918
919 //#define MZT_PUT_SIGNAL(signal, len) { \
920 //      int remain = len; \
921 //      while(remain > 0) { \
922 //              if(buffer != NULL) { \
923 //                      buffer[ptr++] = ((signal != 0) ? 0x80 : 0) | min(remain, 0x7f); \
924 //              } else { \
925 //                      ptr++; \
926 //              } \
927 //              remain -= min(remain, 0x7f); \
928 //      } \
929 //}
930
931 #define MZT_PUT_SIGNAL(signal, len) { \
932         int remain = len; \
933         while(remain > 0) { \
934                 if(buffer != NULL) { \
935                         buffer[ptr++] = (signal != 0) ? 0xff : 0; \
936                 } else { \
937                         ptr++; \
938                 } \
939                 remain--; \
940         } \
941 }
942
943 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
944 #define MZT_PUT_BIT(bit, len) { \
945         for(int l = 0; l < (len); l++) { \
946                 if(bit) { \
947                         MZT_PUT_SIGNAL(1, (int)(120.0 / 16.0 * sample_rate / 22050.0 + 0.5)); \
948                         MZT_PUT_SIGNAL(0, (int)(120.0 / 16.0 * sample_rate / 22050.0 + 0.5)); \
949                 } else { \
950                         MZT_PUT_SIGNAL(1, (int)(60.0 / 16.0 * sample_rate / 22050.0 + 0.5)); \
951                         MZT_PUT_SIGNAL(0, (int)(60.0 / 16.0 * sample_rate / 22050.0 + 0.5)); \
952                 } \
953         } \
954 }
955 #else
956 #define MZT_PUT_BIT(bit, len) { \
957         for(int l = 0; l < (len); l++) { \
958                 if(bit) { \
959                         MZT_PUT_SIGNAL(1, (int)(24.0 * sample_rate / 48000.0 + 0.5)); \
960                         MZT_PUT_SIGNAL(0, (int)(29.0 * sample_rate / 48000.0 + 0.5)); \
961                 } else { \
962                         MZT_PUT_SIGNAL(1, (int)(11.0 * sample_rate / 48000.0 + 0.5)); \
963                         MZT_PUT_SIGNAL(0, (int)(15.0 * sample_rate / 48000.0 + 0.5)); \
964                 } \
965         } \
966 }
967 #endif
968
969 #define MZT_PUT_BYTE(byte) { \
970         MZT_PUT_BIT(1, 1); \
971         for(int j = 0; j < 8; j++) { \
972                 if((byte) & (0x80 >> j)) { \
973                         MZT_PUT_BIT(1, 1); \
974                         count++; \
975                 } else { \
976                         MZT_PUT_BIT(0, 1); \
977                 } \
978         } \
979 }
980
981 #define MZT_PUT_BLOCK(buf, len) { \
982         int count = 0; \
983         for(int i = 0; i < (len); i++) { \
984                 MZT_PUT_BYTE((buf)[i]); \
985         } \
986         uint8_t hi = (count >> 8) & 0xff; \
987         uint8_t lo = (count >> 0) & 0xff; \
988         MZT_PUT_BYTE(hi); \
989         MZT_PUT_BYTE(lo); \
990 }
991
992 int DATAREC::load_mzt_image()
993 {
994         sample_rate = 48000;
995         sample_usec = 1000000. / sample_rate;
996         
997         // get file size
998         play_fio->Fseek(0, FILEIO_SEEK_END);
999         int file_size = play_fio->Ftell();
1000         play_fio->Fseek(0, FILEIO_SEEK_SET);
1001         
1002         // load mzt file
1003         int ptr = 0;
1004         while(file_size > 128) {
1005                 // load header
1006                 uint8_t header[128], ram[0x20000];
1007                 play_fio->Fread(header, sizeof(header), 1);
1008                 file_size -= sizeof(header);
1009                 
1010                 uint16_t size = header[0x12] | (header[0x13] << 8);
1011                 uint16_t offs = header[0x14] | (header[0x15] << 8);
1012                 memset(ram, 0, sizeof(ram));
1013                 play_fio->Fread(ram + offs, size, 1);
1014                 file_size -= size;
1015 //#if defined(_MZ80K) || defined(_MZ700) || defined(_MZ1200) || defined(_MZ1500)
1016 #if 0
1017                 // apply mz700win patch
1018                 if(header[0x40] == 'P' && header[0x41] == 'A' && header[0x42] == 'T' && header[0x43] == ':') {
1019                         int patch_ofs = 0x44;
1020                         for(; patch_ofs < 0x80; ) {
1021                                 uint16_t patch_addr = header[patch_ofs] | (header[patch_ofs + 1] << 8);
1022                                 patch_ofs += 2;
1023                                 if(patch_addr == 0xffff) {
1024                                         break;
1025                                 }
1026                                 int patch_len = header[patch_ofs++];
1027                                 for(int i = 0; i < patch_len; i++) {
1028                                         ram[patch_addr + i] = header[patch_ofs++];
1029                                 }
1030                         }
1031                         for(int i = 0x40; i < patch_ofs; i++) {
1032                                 header[i] = 0;
1033                         }
1034                 }
1035 #endif
1036                 // output to buffer
1037                 MZT_PUT_SIGNAL(0, sample_rate);
1038 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
1039                 // Bin2Wav Ver 0.03
1040                 MZT_PUT_BIT(0, 22000);
1041                 MZT_PUT_BIT(1, 40);
1042                 MZT_PUT_BIT(0, 41);
1043                 MZT_PUT_BLOCK(header, 128);
1044                 MZT_PUT_BIT(1, 1);
1045                 MZT_PUT_SIGNAL(1, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1046                 MZT_PUT_SIGNAL(0, (int)(22.0 * sample_rate / 22050.0 + 0.5));
1047                 MZT_PUT_SIGNAL(0, sample_rate);
1048                 MZT_PUT_BIT(0, 11000);
1049                 MZT_PUT_BIT(1, 20);
1050                 MZT_PUT_BIT(0, 21);
1051                 MZT_PUT_BLOCK(ram + offs, size);
1052                 MZT_PUT_BIT(1, 1);
1053 #else
1054                 // format info written in \8e\8e\8c±\82É\8fo\82éX1
1055                 MZT_PUT_BIT(0, 10000);
1056                 MZT_PUT_BIT(1, 40);
1057                 MZT_PUT_BIT(0, 40);
1058                 MZT_PUT_BIT(1, 1);
1059                 MZT_PUT_BLOCK(header, 128);
1060                 MZT_PUT_BIT(1, 1);
1061                 MZT_PUT_BIT(0, 256);
1062                 MZT_PUT_BLOCK(header, 128);
1063                 MZT_PUT_BIT(1, 1);
1064                 MZT_PUT_SIGNAL(0, sample_rate);
1065                 MZT_PUT_BIT(0, 10000);
1066                 MZT_PUT_BIT(1, 20);
1067                 MZT_PUT_BIT(0, 20);
1068                 MZT_PUT_BIT(1, 1);
1069                 MZT_PUT_BLOCK(ram + offs, size);
1070                 MZT_PUT_BIT(1, 1);
1071 #endif
1072         }
1073         return ptr;
1074 }
1075
1076 // NEC PC-6001/6601 series tape image
1077
1078 #define P6_PUT_1200HZ() { \
1079         if(buffer != NULL) { \
1080                 for(int p = 0; p < 20; p++) buffer[ptr++] = 0xff; \
1081                 for(int p = 0; p < 20; p++) buffer[ptr++] = 0x00; \
1082         } else { \
1083                 ptr += 40; \
1084         } \
1085 }
1086
1087 #define P6_PUT_2400HZ() { \
1088         if(buffer != NULL) { \
1089                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1090                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1091         } else { \
1092                 ptr += 20; \
1093         } \
1094 }
1095
1096 #define P6_PUT_2400HZ_X2() { \
1097         if(buffer != NULL) { \
1098                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1099                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1100                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0xff; \
1101                 for(int p = 0; p < 10; p++) buffer[ptr++] = 0x00; \
1102         } else { \
1103                 ptr += 40; \
1104         } \
1105 }
1106
1107 int DATAREC::load_p6_image(bool is_p6t)
1108 {
1109         sample_rate = 48000;
1110         sample_usec = 1000000. / sample_rate;
1111         
1112         int ptr = 0, remain = 0x10000, data;
1113         if(is_p6t) {
1114                 // get info block offset
1115                 play_fio->Fseek(-4, FILEIO_SEEK_END);
1116                 int length = play_fio->FgetInt32();
1117                 // check info block
1118                 play_fio->Fseek(length, FILEIO_SEEK_SET);
1119                 char id_p = play_fio->Fgetc();
1120                 char id_6 = play_fio->Fgetc();
1121                 uint8_t ver = play_fio->FgetUint8();
1122                 if(id_p == 'P' && id_6 == '6' && ver == 2) {
1123                         uint8_t blocks = play_fio->FgetUint8();
1124                         if(blocks >= 1) {
1125                                 play_fio->FgetUint8();
1126                                 play_fio->FgetUint8();
1127                                 play_fio->FgetUint8();
1128                                 uint16_t cmd = play_fio->FgetUint16();
1129                                 play_fio->Fseek(cmd, FILEIO_SEEK_CUR);
1130                                 uint16_t exp = play_fio->FgetUint16();
1131                                 play_fio->Fseek(exp, FILEIO_SEEK_CUR);
1132                                 // check 1st data block
1133                                 char id_t = play_fio->Fgetc();
1134                                 char id_i = play_fio->Fgetc();
1135                                 if(id_t == 'T' && id_i == 'I') {
1136                                         play_fio->FgetUint8();
1137                                         play_fio->Fseek(16, FILEIO_SEEK_CUR);
1138                                         uint16_t baud = play_fio->FgetUint16(); // 600 or 1200
1139                                         sample_rate = sample_rate * baud / 1200;
1140                                         sample_usec = 1000000. / sample_rate;
1141                                 }
1142                         }
1143                         remain = min(length, 0x10000);
1144                 }
1145         }
1146         play_fio->Fseek(0, FILEIO_SEEK_SET);
1147         
1148         for(int i = 0; i < 9600; i++) {
1149                 P6_PUT_2400HZ();
1150         }
1151         for(int i = 0; i < 16; i++) {
1152                 data = play_fio->Fgetc();
1153                 P6_PUT_1200HZ();
1154                 for(int j = 0; j < 8; j++) {
1155                         if(data & (1 << j)) {
1156                                 P6_PUT_2400HZ_X2();
1157                         } else {
1158                                 P6_PUT_1200HZ();
1159                         }
1160                 }
1161                 P6_PUT_2400HZ_X2();
1162                 P6_PUT_2400HZ_X2();
1163                 P6_PUT_2400HZ_X2();
1164                 remain--;
1165         }
1166 //      for(int i = 0; i < 1280; i++) {
1167         for(int i = 0; i < 2400; i++) {
1168                 P6_PUT_2400HZ();
1169         }
1170         while((data = play_fio->Fgetc()) != EOF && remain > 0) {
1171                 P6_PUT_1200HZ();
1172                 for(int j = 0; j < 8; j++) {
1173                         if(data & (1 << j)) {
1174                                 P6_PUT_2400HZ_X2();
1175                         } else {
1176                                 P6_PUT_1200HZ();
1177                         }
1178                 }
1179                 P6_PUT_2400HZ_X2();
1180                 P6_PUT_2400HZ_X2();
1181                 P6_PUT_2400HZ_X2();
1182                 remain--;
1183         }
1184 #if 1
1185         for(int i = 0; i < 16; i++) {
1186                 P6_PUT_1200HZ();
1187                 for(int j = 0; j < 8; j++) {
1188                         P6_PUT_1200HZ();
1189                 }
1190                 P6_PUT_2400HZ_X2();
1191                 P6_PUT_2400HZ_X2();
1192                 P6_PUT_2400HZ_X2();
1193         }
1194 #endif
1195         return ptr;
1196 }
1197
1198 // standard cas image for my emulator
1199
1200 static const uint8_t msx_cas_header[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};
1201
1202 int DATAREC::load_cas_image()
1203 {
1204         sample_rate = 48000;
1205         sample_usec = 1000000. / sample_rate;
1206         
1207         // SORD m5 or NEC PC-6001 series cas image ?
1208         static const uint8_t momomomomomo[6] = {0xd3, 0xd3, 0xd3, 0xd3, 0xd3, 0xd3};
1209         uint8_t tmp_header[8];
1210         play_fio->Fseek(0, FILEIO_SEEK_SET);
1211         play_fio->Fread(tmp_header, sizeof(tmp_header), 1);
1212         
1213         if(memcmp(tmp_header, "SORDM5", 6) == 0) {
1214                 return load_m5_cas_image();
1215         } else if(memcmp(tmp_header, msx_cas_header, 8) == 0) {
1216                 return load_msx_cas_image();
1217         } else if(memcmp(tmp_header, momomomomomo, 6) == 0) {
1218                 return load_p6_image(false);
1219         }
1220         
1221         // this is the standard cas image for my emulator
1222         play_fio->Fseek(0, FILEIO_SEEK_SET);
1223         int ptr = 0, data;
1224         while((data = play_fio->Fgetc()) != EOF) {
1225                 for(int i = 0; i < (data & 0x7f); i++) {
1226                         if(buffer != NULL) {
1227                                 buffer[ptr] = (data & 0x80) ? 255 : 0;
1228                         }
1229                         ptr++;
1230                 }
1231         }
1232         return ptr;
1233 }
1234
1235 // SORD M5 tape image
1236
1237 #define M5_PUT_BIT(val, len) { \
1238         int remain = len; \
1239         while(remain > 0) { \
1240                 if(buffer != NULL) { \
1241                         buffer[ptr] = val ? 0 : 0xff; \
1242                 } \
1243                 ptr++; \
1244                 remain--; \
1245         } \
1246 }
1247
1248 #define M5_PUT_BYTE(data) { \
1249         for(int j = 0; j < 10; j++) { \
1250                 int bit = (j == 0) ? 1 : (j == 1) ? 0 : ((data >> (j - 2)) & 1); \
1251                 if(bit) { \
1252                         M5_PUT_BIT(0xff, 8); \
1253                         M5_PUT_BIT(0x00, 7); \
1254                 } else { \
1255                         M5_PUT_BIT(0xff, 16); \
1256                         M5_PUT_BIT(0x00, 14); \
1257                 } \
1258         } \
1259 }
1260
1261 int DATAREC::load_m5_cas_image()
1262 {
1263         play_fio->Fseek(16, FILEIO_SEEK_SET);
1264         int ptr = 0, block_type;
1265         
1266         while((block_type = play_fio->Fgetc()) != EOF) {
1267                 if(block_type != 'H' && block_type != 'D') {
1268                         return 0;
1269                 }
1270                 int block_size = play_fio->Fgetc();
1271                 
1272                 if(block_type == 'H') {
1273                         M5_PUT_BIT(0x00, 1);
1274                 }
1275                 for(int i = 0; i < (block_type == 'H' ? 945 : 59); i++) {
1276                         M5_PUT_BIT(0xff, 8);
1277                         M5_PUT_BIT(0x00, 7);
1278                 }
1279                 M5_PUT_BYTE(block_type);
1280                 M5_PUT_BYTE(block_size);
1281                 
1282                 for(int i = 0; i < ((block_size == 0) ? 0x101 : (block_size + 1)); i++) {
1283                         uint8_t data = play_fio->Fgetc();
1284                         M5_PUT_BYTE(data);
1285                 }
1286                 M5_PUT_BIT(0xff, 8);
1287                 M5_PUT_BIT(0x00, 7);
1288         }
1289         M5_PUT_BIT(0x00, 1);
1290         return ptr;
1291 }
1292
1293 // ASCII MSX tape image (fMSX)
1294 // MAME/MESS /src/lib/formats/fmsx_cas.c by Mr.Sean Young
1295
1296 #define CAS_PERIOD              (16)
1297 #define CAS_HEADER_PERIODS      (4000)
1298 #define CAS_EMPTY_PERIODS       (1000)
1299
1300 int DATAREC::load_msx_cas_image()
1301 {
1302         sample_rate = 22050;
1303         sample_usec = 1000000. / sample_rate;
1304         
1305         play_fio->Fseek(0, FILEIO_SEEK_END);
1306         int cas_size = play_fio->Ftell();
1307         uint8_t *bytes = (uint8_t *)malloc(cas_size);
1308         play_fio->Fseek(0, FILEIO_SEEK_SET);
1309         play_fio->Fread(bytes, cas_size, 1);
1310         
1311         int cas_pos, bit, state = 1, samples_pos, size, n, i, p;
1312         
1313         cas_pos = 0;
1314         samples_pos = 0;
1315         
1316         while(/*samples_pos < sample_count && */cas_pos < cas_size) {
1317                 /* Check if we need to output a header */
1318                 if(cas_pos + 8 < cas_size) {
1319                         if(!memcmp( bytes + cas_pos, msx_cas_header, 8)) {
1320                                 /* Write CAS_EMPTY_PERIODS of silence */
1321                                 n = CAS_EMPTY_PERIODS * CAS_PERIOD;
1322                                 while(n--) {
1323                                         if(buffer != NULL) {
1324                                                 buffer[samples_pos] = 0;
1325                                         }
1326                                         samples_pos++;
1327                                 }
1328                                 /* Write CAS_HEADER_PERIODS of header (high frequency) */
1329                                 for(i = 0; i < CAS_HEADER_PERIODS * 4 ; i++) {
1330                                         for(n = 0; n < CAS_PERIOD / 4; n++) {
1331                                                 if(buffer != NULL) {
1332                                                         buffer[samples_pos + n] = (state ? 0xff : 0);
1333                                                 }
1334                                         }
1335                                         samples_pos += CAS_PERIOD / 4 ;
1336                                         state = !state;
1337                                 }
1338                                 cas_pos += 8;
1339                         }
1340                 }
1341                 
1342                 for(i = 0; i <= 11; i++) {
1343                         if(i == 0) {
1344                                 bit = 0;
1345                         } else if(i < 9) {
1346                                 bit = (bytes[cas_pos] & (1 << (i - 1) ) );
1347                         } else {
1348                                 bit = 1;
1349                         }
1350                         
1351                         /* write this one bit */
1352                         for(n = 0; n < (bit ? 4 : 2); n++) {
1353                                 size = (bit ? CAS_PERIOD / 4 : CAS_PERIOD / 2);
1354                                 for(p = 0; p < size; p++) {
1355                                         if(buffer != NULL) {
1356                                                 buffer[samples_pos + p] = (state ? 0xff : 0);
1357                                         }
1358                                 }
1359                                 state = !state;
1360                                 samples_pos += size;
1361                         }
1362                 }
1363                 cas_pos++;
1364         }
1365         free(bytes);
1366         return samples_pos;
1367 }
1368
1369 void DATAREC::mix(int32_t* buffer, int cnt)
1370 {
1371         int32_t* buffer_tmp = buffer;
1372         
1373         if(config.tape_sound && pcm_changed && remote && (play || rec) && ff_rew == 0) {
1374                 bool signal = ((play && in_signal) || (rec && out_signal));
1375                 if(signal) {
1376                         pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
1377                 } else {
1378                         pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
1379                 }
1380                 int clocks = pcm_positive_clocks + pcm_negative_clocks;
1381                 int sample = clocks ? (pcm_max_vol * pcm_positive_clocks - pcm_max_vol * pcm_negative_clocks) / clocks : signal ? pcm_max_vol : -pcm_max_vol;
1382                 
1383                 pcm_last_vol_l = apply_volume(sample, pcm_volume_l);
1384                 pcm_last_vol_r = apply_volume(sample, pcm_volume_r);
1385                 
1386                 for(int i = 0; i < cnt; i++) {
1387                         *buffer++ += pcm_last_vol_l; // L
1388                         *buffer++ += pcm_last_vol_r; // R
1389                 }
1390         } else {
1391                 // suppress petite noise when go to mute
1392                 for(int i = 0; i < cnt; i++) {
1393                         *buffer++ += pcm_last_vol_l; // L
1394                         *buffer++ += pcm_last_vol_r; // R
1395                         
1396                         if(pcm_last_vol_l > 0) {
1397                                 pcm_last_vol_l--;
1398                         } else if(pcm_last_vol_l < 0) {
1399                                 pcm_last_vol_l++;
1400                         }
1401                         if(pcm_last_vol_r > 0) {
1402                                 pcm_last_vol_r--;
1403                         } else if(pcm_last_vol_r < 0) {
1404                                 pcm_last_vol_r++;
1405                         }
1406                 }
1407         }
1408         pcm_prev_clock = get_current_clock();
1409         pcm_positive_clocks = pcm_negative_clocks = 0;
1410         
1411 #ifdef DATAREC_SOUND
1412         if(config.tape_sound) {
1413                 int32_t sound_vol_l = apply_volume(sound_sample, sound_volume_l);
1414                 int32_t sound_vol_r = apply_volume(sound_sample, sound_volume_r);
1415                 buffer = buffer_tmp; // restore
1416                 for(int i = 0; i < cnt; i++) {
1417                         *buffer += sound_vol_l; // L
1418                         *buffer += sound_vol_r; // R
1419                 }
1420         }
1421 #endif
1422 }
1423
1424 void DATAREC::set_volume(int ch, int decibel_l, int decibel_r)
1425 {
1426         if(ch == 0) {
1427                 pcm_volume_l = decibel_to_volume(decibel_l);
1428                 pcm_volume_r = decibel_to_volume(decibel_r);
1429 #ifdef DATAREC_SOUND
1430         } else if(ch == 1) {
1431                 sound_volume_l = decibel_to_volume(decibel_l);
1432                 sound_volume_r = decibel_to_volume(decibel_r);
1433 #endif
1434         }
1435 }
1436
1437 #define STATE_VERSION   6
1438
1439 void DATAREC::save_state(FILEIO* state_fio)
1440 {
1441         state_fio->FputUint32(STATE_VERSION);
1442         state_fio->FputInt32(this_device_id);
1443         
1444         state_fio->FputBool(play);
1445         state_fio->FputBool(rec);
1446         state_fio->FputBool(remote);
1447         state_fio->FputBool(trigger);
1448         state_fio->Fwrite(rec_file_path, sizeof(rec_file_path), 1);
1449         if(rec && rec_fio->IsOpened()) {
1450                 int length_tmp = (int)rec_fio->Ftell();
1451                 rec_fio->Fseek(0, FILEIO_SEEK_SET);
1452                 state_fio->FputInt32(length_tmp);
1453                 while(length_tmp != 0) {
1454                         uint8_t buffer_tmp[1024];
1455                         int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1456                         rec_fio->Fread(buffer_tmp, length_rw, 1);
1457                         state_fio->Fwrite(buffer_tmp, length_rw, 1);
1458                         length_tmp -= length_rw;
1459                 }
1460         } else {
1461                 state_fio->FputInt32(0);
1462         }
1463         state_fio->FputInt32(ff_rew);
1464         state_fio->FputBool(in_signal);
1465         state_fio->FputBool(out_signal);
1466         state_fio->FputUint32(prev_clock);
1467         state_fio->FputInt32(positive_clocks);
1468         state_fio->FputInt32(negative_clocks);
1469         state_fio->FputInt32(signal_changed);
1470         state_fio->FputInt32(register_id);
1471         state_fio->FputInt32(sample_rate);
1472         state_fio->FputDouble(sample_usec);
1473         state_fio->FputInt32(buffer_ptr);
1474         if(buffer) {
1475                 state_fio->FputInt32(buffer_length);
1476                 state_fio->Fwrite(buffer, buffer_length, 1);
1477         } else {
1478                 state_fio->FputInt32(0);
1479         }
1480         if(buffer_bak) {
1481                 state_fio->FputInt32(buffer_length);
1482                 state_fio->Fwrite(buffer_bak, buffer_length, 1);
1483         } else {
1484                 state_fio->FputInt32(0);
1485         }
1486 #ifdef DATAREC_SOUND
1487         if(sound_buffer) {
1488                 state_fio->FputInt32(sound_buffer_length);
1489                 state_fio->Fwrite(sound_buffer, sound_buffer_length, 1);
1490         } else {
1491                 state_fio->FputInt32(0);
1492         }
1493         state_fio->FputInt16(sound_sample);
1494 #endif
1495         state_fio->FputBool(is_wav);
1496         state_fio->FputBool(is_tap);
1497         if(apss_buffer) {
1498                 state_fio->FputInt32(apss_buffer_length);
1499                 state_fio->Fwrite(apss_buffer, apss_buffer_length, 1);
1500         } else {
1501                 state_fio->FputInt32(0);
1502         }
1503         state_fio->FputInt32(apss_ptr);
1504         state_fio->FputInt32(apss_count);
1505         state_fio->FputInt32(apss_remain);
1506         state_fio->FputBool(apss_signals);
1507         state_fio->FputInt32(pcm_changed);
1508         state_fio->FputUint32(pcm_prev_clock);
1509         state_fio->FputInt32(pcm_positive_clocks);
1510         state_fio->FputInt32(pcm_negative_clocks);
1511 }
1512
1513 bool DATAREC::load_state(FILEIO* state_fio)
1514 {
1515         close_file();
1516         
1517         if(state_fio->FgetUint32() != STATE_VERSION) {
1518                 return false;
1519         }
1520         if(state_fio->FgetInt32() != this_device_id) {
1521                 return false;
1522         }
1523         play = state_fio->FgetBool();
1524         rec = state_fio->FgetBool();
1525         remote = state_fio->FgetBool();
1526         trigger = state_fio->FgetBool();
1527         state_fio->Fread(rec_file_path, sizeof(rec_file_path), 1);
1528         int length_tmp = state_fio->FgetInt32();
1529         if(rec) {
1530                 rec_fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
1531                 while(length_tmp != 0) {
1532                         uint8_t buffer_tmp[1024];
1533                         int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
1534                         state_fio->Fread(buffer_tmp, length_rw, 1);
1535                         if(rec_fio->IsOpened()) {
1536                                 rec_fio->Fwrite(buffer_tmp, length_rw, 1);
1537                         }
1538                         length_tmp -= length_rw;
1539                 }
1540         }
1541         ff_rew = state_fio->FgetInt32();
1542         in_signal = state_fio->FgetBool();
1543         out_signal = state_fio->FgetBool();
1544         prev_clock = state_fio->FgetUint32();
1545         positive_clocks = state_fio->FgetInt32();
1546         negative_clocks = state_fio->FgetInt32();
1547         signal_changed = state_fio->FgetInt32();
1548         register_id = state_fio->FgetInt32();
1549         sample_rate = state_fio->FgetInt32();
1550         sample_usec = state_fio->FgetDouble();
1551         buffer_ptr = state_fio->FgetInt32();
1552         if((buffer_length = state_fio->FgetInt32()) != 0) {
1553                 buffer = (uint8_t *)malloc(buffer_length);
1554                 state_fio->Fread(buffer, buffer_length, 1);
1555         }
1556         if((length_tmp = state_fio->FgetInt32()) != 0) {
1557                 buffer_bak = (uint8_t *)malloc(length_tmp);
1558                 state_fio->Fread(buffer_bak, length_tmp, 1);
1559         }
1560 #ifdef DATAREC_SOUND
1561         if((sound_buffer_length = state_fio->FgetInt32()) != 0) {
1562                 sound_buffer = (int16_t *)malloc(sound_buffer_length);
1563                 state_fio->Fread(sound_buffer, sound_buffer_length, 1);
1564         }
1565         sound_sample = state_fio->FgetInt16();
1566 #endif
1567         is_wav = state_fio->FgetBool();
1568         is_tap = state_fio->FgetBool();
1569         if((apss_buffer_length = state_fio->FgetInt32()) != 0) {
1570                 apss_buffer = (bool *)malloc(apss_buffer_length);
1571                 state_fio->Fread(apss_buffer, apss_buffer_length, 1);
1572         }
1573         apss_ptr = state_fio->FgetInt32();
1574         apss_count = state_fio->FgetInt32();
1575         apss_remain = state_fio->FgetInt32();
1576         apss_signals = state_fio->FgetBool();
1577         pcm_changed = state_fio->FgetInt32();
1578         pcm_prev_clock = state_fio->FgetUint32();
1579         pcm_positive_clocks = state_fio->FgetInt32();
1580         pcm_negative_clocks = state_fio->FgetInt32();
1581         
1582         // post process
1583         pcm_last_vol_l = pcm_last_vol_r = 0;
1584         return true;
1585 }
1586