2 Skelton for retropc emulator
4 Author : Takeda.Toshiya
13 #define EVENT_SIGNAL 0
16 #ifndef DATAREC_FF_REW_SPEED
17 #define DATAREC_FF_REW_SPEED 10
20 void DATAREC::initialize()
22 play_fio = new FILEIO();
23 rec_fio = new FILEIO();
25 memset(rec_file_path, sizeof(rec_file_path), 1);
26 play = rec = remote = trigger = false;
28 in_signal = out_signal = false;
31 buffer = buffer_bak = NULL;
36 buffer_ptr = buffer_length = 0;
37 is_wav = is_tap = false;
40 pcm_last_vol_l = pcm_last_vol_r = 0;
44 register_frame_event(this);
50 pcm_prev_clock = get_current_clock();
51 pcm_positive_clocks = pcm_negative_clocks = 0;
54 void DATAREC::release()
61 void DATAREC::write_signal(int id, uint32_t data, uint32_t mask)
63 bool signal = ((data & mask) != 0);
65 if(id == SIG_DATAREC_MIC) {
66 if(out_signal != signal) {
69 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
71 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
73 pcm_prev_clock = get_current_clock();
79 positive_clocks += get_passed_clock(prev_clock);
81 negative_clocks += get_passed_clock(prev_clock);
83 prev_clock = get_current_clock();
87 } else if(id == SIG_DATAREC_REMOTE) {
89 } else if(id == SIG_DATAREC_TRIG) {
90 // L->H: remote signal is switched
91 if(signal && !trigger) {
98 void DATAREC::event_frame()
103 if(signal_changed > 10 && ff_rew == 0 && !config.tape_sound) {
104 request_skip_frames();
109 void DATAREC::event_callback(int event_id, int err)
111 if(event_id == EVENT_SIGNAL) {
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());
118 emu->out_message(_T("CMT: Play (%d %%)"), get_tape_position());
120 bool signal = in_signal;
122 if(buffer_ptr >= 0 && buffer_ptr < buffer_length) {
123 signal = ((buffer[buffer_ptr] & 0x80) != 0);
125 if(sound_buffer != NULL && ff_rew == 0) {
126 sound_sample = sound_buffer[buffer_ptr];
133 if((buffer_ptr = max(buffer_ptr - 1, 0)) == 0) {
134 set_remote(false); // top of tape
138 if((buffer_ptr = min(buffer_ptr + 1, buffer_length)) == buffer_length) {
139 set_remote(false); // end of tape
146 if(buffer_bak != NULL) {
147 memcpy(buffer, buffer_bak, buffer_length);
150 set_remote(false); // top of tape
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
159 signal = ((buffer[buffer_ptr] & 0x80) != 0);
161 signal = ((buffer[buffer_ptr] & 0x80) != 0);
162 uint8_t tmp = buffer[buffer_ptr];
163 buffer[buffer_ptr] = (tmp & 0x80) | ((tmp & 0x7f) - 1);
169 // notify the signal is changed
170 if(signal != in_signal) {
172 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
174 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
176 pcm_prev_clock = get_current_clock();
180 write_signals(&outputs_ear, in_signal ? 0xffffffff : 0);
183 if(apss_buffer != NULL) {
184 int ptr = (apss_ptr++) % (sample_rate * 2);
185 if(apss_buffer[ptr]) {
191 apss_buffer[ptr] = in_signal;
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) {
197 if(apss_remain > 0) {
199 } else if(apss_remain < 0) {
202 write_signals(&outputs_apss, 0xffffffff);
203 apss_signals = false;
207 write_signals(&outputs_apss, 0);
215 positive_clocks += get_passed_clock(prev_clock);
217 negative_clocks += get_passed_clock(prev_clock);
220 if(positive_clocks != 0 || negative_clocks != 0) {
221 buffer[buffer_ptr] = (255 * positive_clocks) / (positive_clocks + negative_clocks);
223 buffer[buffer_ptr] = 0;
225 if(++buffer_ptr >= buffer_length) {
227 for(int i = 0; i < buffer_length; i += 8) {
229 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
230 if(i + j < buffer_length && buffer[i + j] >= 0x80) {
234 rec_fio->FputUint8(val);
237 rec_fio->Fwrite(buffer, buffer_length, 1);
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);
249 buffer[buffer_ptr] = cur_signal ? 0x80 : 0;
251 buffer[buffer_ptr]++;
253 prev_clock = get_current_clock();
254 positive_clocks = negative_clocks = 0;
259 void DATAREC::set_remote(bool value)
261 if(remote != value) {
267 void DATAREC::set_ff_rew(int value)
269 if(ff_rew != value) {
270 if(register_id != -1) {
271 cancel_event(this, register_id);
275 apss_signals = false;
280 bool DATAREC::do_apss(int value)
287 set_ff_rew(value > 0 ? 1 : -1);
290 while(apss_remain != 0 && remote) {
291 event_callback(EVENT_SIGNAL, 0);
293 result = (apss_remain == 0);
302 emu->out_message(_T("CMT: APSS Forward (%d %%)"), get_tape_position());
304 emu->out_message(_T("CMT: APSS Forward"));
308 emu->out_message(_T("CMT: APSS Rewind (%d %%)"), get_tape_position());
310 emu->out_message(_T("CMT: APSS Rewind"));
316 void DATAREC::update_event()
318 if(remote && (play || rec)) {
319 if(register_id == -1) {
321 register_event(this, EVENT_SIGNAL, sample_usec / DATAREC_FF_REW_SPEED, true, ®ister_id);
324 emu->out_message(_T("CMT: Record"));
326 // ToDo sample_usec -> sample_usec * 2
327 register_event(this, EVENT_SIGNAL, sample_usec, true, ®ister_id);
329 prev_clock = get_current_clock();
330 positive_clocks = negative_clocks = 0;
333 if(register_id != -1) {
334 cancel_event(this, register_id);
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)"));
342 emu->out_message(_T("CMT: Stop (%d %%)"), get_tape_position());
345 emu->out_message(_T("CMT: Stop"));
353 if(!(play && remote)) {
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);
363 bool DATAREC::play_tape(const _TCHAR* file_path)
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;
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);
378 play = is_wav = true;
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);
385 play = is_wav = true;
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);
392 play = is_wav = true;
394 } else if(check_file_extension(file_path, _T(".mtw"))) {
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;
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;
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);
415 play = is_wav = true;
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);
422 play = is_wav = true;
428 if(!is_wav && buffer_length != 0) {
429 buffer_bak = (uint8_t *)malloc(buffer_length);
430 memcpy(buffer_bak, buffer, buffer_length);
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);
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);
452 bool DATAREC::rec_tape(const _TCHAR* file_path)
456 if(rec_fio->Fopen(file_path, FILEIO_READ_WRITE_NEW_BINARY)) {
457 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
459 sample_usec = 1000000. / sample_rate;
460 buffer_length = 1024 * 1024;
461 buffer = (uint8_t *)malloc(buffer_length);
463 if(check_file_extension(file_path, _T(".wav"))) {
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);
469 } else if(check_file_extension(file_path, _T(".tap"))) {
471 rec_fio->FputUint32((uint32_t)sample_rate);
472 is_wav = is_tap = true;
475 buffer[0] = out_signal ? 0x80 : 0;
483 void DATAREC::close_tape()
487 play = rec = is_wav = is_tap = false;
488 buffer_ptr = buffer_length = 0;
492 write_signals(&outputs_ear, 0);
496 void DATAREC::close_file()
498 if(play_fio->IsOpened()) {
501 if(rec_fio->IsOpened()) {
504 for(int i = 0; i < buffer_ptr; i += 8) {
506 for(int j = 0, bit = 0x80; j < 8; j++, bit >>= 1) {
507 if(i + j < buffer_ptr && buffer[i + j] >= 0x80) {
511 rec_fio->FputUint8(val);
516 rec_fio->Fwrite(buffer, buffer_ptr + 1, 1);
525 if(buffer_bak != NULL) {
530 if(sound_buffer != NULL) {
535 if(apss_buffer != NULL) {
541 // standard PCM wave file
543 int DATAREC::load_wav_image(int offset)
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)) {
554 play_fio->Fseek(header.fmt_chunk.size - 16, FILEIO_SEEK_CUR);
556 play_fio->Fread(&chunk, sizeof(chunk), 1);
557 if(strncmp(chunk.id, "data", 4) == 0) {
560 play_fio->Fseek(chunk.size, FILEIO_SEEK_CUR);
563 int samples = chunk.size / header.channels, loaded_samples = 0;
564 if(header.sample_bits == 16) {
567 sample_rate = header.sample_rate;
568 sample_usec = 1000000. / sample_rate;
572 #define TMP_LENGTH (0x10000 * header.channels)
574 uint8_t *tmp_buffer = (uint8_t *)malloc(TMP_LENGTH);
575 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1);
577 #define GET_SAMPLE { \
578 for(int ch = 0; ch < header.channels; ch++) { \
579 if(header.sample_bits == 16) { \
586 pair.b.l = tmp_buffer[tmp_ptr++]; \
587 pair.b.h = tmp_buffer[tmp_ptr++]; \
588 sample[ch] = pair.s16; \
590 sample[ch] = (tmp_buffer[tmp_ptr++] - 128) * 256; \
593 if(tmp_ptr == TMP_LENGTH) { \
594 play_fio->Fread(tmp_buffer, TMP_LENGTH, 1); \
600 if(!config.wave_shaper || header.channels > 1) {
602 if(!config.wave_shaper) {
604 buffer = (uint8_t *)malloc(samples);
606 if(header.channels > 1) {
607 sound_buffer_length = samples * sizeof(int16_t);
608 sound_buffer = (int16_t *)malloc(sound_buffer_length);
611 bool prev_signal = false;
612 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
615 bool signal = (sample[0] > (prev_signal ? -1024 : 1024));
616 buffer[i] = (signal ? 0xff : 0);
618 if(header.channels > 1) {
619 sound_buffer[i] = sample[1];
622 prev_signal = signal;
624 loaded_samples = samples;
627 int16_t *wav_buffer = (int16_t *)malloc(samples * sizeof(int16_t));
628 for(int i = 0, tmp_ptr = 0; i < samples; i++) {
631 wav_buffer[i] = sample[0];
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];
643 if(max_sample - min_sample > 4096) {
644 zero_buffer[i] = (max_sample + min_sample) / 2;
646 zero_buffer[i] = wav_buffer[i];
649 for(int i = 0; i < samples; i++) {
650 wav_buffer[i] -= zero_buffer[(i < width) ? width : (i < samples - width) ? i : (samples - width - 1)];
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));
663 for(int t = 0; t < 3; t++) {
664 int count_positive = 0, count_negative = 0;
665 bool prev_signal = false;
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);
674 if(!prev_signal && signal) {
676 if(count_positive < max_threshold && count_positive > min_threshold && count_negative > min_threshold) {
677 counts[count_positive]++;
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) {
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;
693 loaded_samples += count_p + count_n;
696 count_positive = count_negative = 0;
703 prev_signal = signal;
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];
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);
716 half_tmp = (int)(header.sample_rate * FREQ_SCALE / 1920.0 / 2.0 + 0.5);
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];
724 double lo_tmp = (double)sum_value / (double)sum_count;
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];
731 double hi_tmp = (double)sum_value / (double)sum_count;
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);
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) {
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;
751 loaded_samples += count_p + count_n;
755 buffer = (uint8_t *)malloc(loaded_samples);
757 if(header.channels > 1) {
758 sound_buffer_length = loaded_samples * sizeof(int16_t);
759 sound_buffer = (int16_t *)malloc(sound_buffer_length);
770 return loaded_samples;
773 void DATAREC::save_wav_image()
775 // write samples remained in buffer
777 rec_fio->Fwrite(buffer, buffer_ptr, 1);
779 uint32_t length = rec_fio->Ftell();
781 wav_header_t wav_header;
782 wav_chunk_t wav_chunk;
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;
796 memcpy(wav_chunk.id, "data", 4);
797 wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);
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);
804 // FUJITSU FM-7 series tape image
806 #define T77_PUT_SIGNAL(signal, len) { \
808 while(remain > 0) { \
809 if(buffer != NULL) { \
810 buffer[ptr++] = (signal) ? 0xff : 0x7f; \
818 int DATAREC::load_t77_image()
821 sample_rate = (int)(1000000.0 / sample_usec + 0.5);
826 int file_size = (int)play_fio->FileLength();
829 return 0; // over 2GB
831 play_fio->Fseek(0, FILEIO_SEEK_SET);
832 play_fio->Fread(tmpbuf, 16, 1);
834 if(strcmp((char *)tmpbuf, "XM7 TAPE IMAGE 0") != 0) {
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;
844 if((file_size -= 2) < 0) {
848 T77_PUT_SIGNAL((h & 0x80) != 0, v & 0x7fff);
854 // SHARP X1 series tape image
857 new tape file format for t-tune (from tape_fmt.txt)
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^
871 int DATAREC::load_tap_image()
874 play_fio->Fseek(0, FILEIO_SEEK_END);
875 int file_size = play_fio->Ftell();
876 play_fio->Fseek(0, FILEIO_SEEK_SET);
880 play_fio->Fread(header, 4, 1);
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);
886 if(play_fio->Fgetc() != 0x01) {
887 // unknown data format
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;
895 play_fio->Fread(header, 4, 1);
897 play_fio->Fread(header, 4, 1);
900 sample_rate = header[0] | (header[1] << 8) | (header[2] << 16) | (header[3] << 24);
901 sample_usec = 1000000. / sample_rate;
906 while((data = play_fio->Fgetc()) != EOF) {
907 for(int i = 0, bit = 0x80; i < 8; i++, bit >>= 1) {
909 buffer[ptr] = ((data & bit) != 0) ? 255 : 0;
917 // SHARP MZ series tape image
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); \
927 // remain -= min(remain, 0x7f); \
931 #define MZT_PUT_SIGNAL(signal, len) { \
933 while(remain > 0) { \
934 if(buffer != NULL) { \
935 buffer[ptr++] = (signal != 0) ? 0xff : 0; \
943 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
944 #define MZT_PUT_BIT(bit, len) { \
945 for(int l = 0; l < (len); l++) { \
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)); \
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)); \
956 #define MZT_PUT_BIT(bit, len) { \
957 for(int l = 0; l < (len); l++) { \
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)); \
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)); \
969 #define MZT_PUT_BYTE(byte) { \
971 for(int j = 0; j < 8; j++) { \
972 if((byte) & (0x80 >> j)) { \
981 #define MZT_PUT_BLOCK(buf, len) { \
983 for(int i = 0; i < (len); i++) { \
984 MZT_PUT_BYTE((buf)[i]); \
986 uint8_t hi = (count >> 8) & 0xff; \
987 uint8_t lo = (count >> 0) & 0xff; \
992 int DATAREC::load_mzt_image()
995 sample_usec = 1000000. / sample_rate;
998 play_fio->Fseek(0, FILEIO_SEEK_END);
999 int file_size = play_fio->Ftell();
1000 play_fio->Fseek(0, FILEIO_SEEK_SET);
1004 while(file_size > 128) {
1006 uint8_t header[128], ram[0x20000];
1007 play_fio->Fread(header, sizeof(header), 1);
1008 file_size -= sizeof(header);
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);
1015 //#if defined(_MZ80K) || defined(_MZ700) || defined(_MZ1200) || defined(_MZ1500)
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);
1023 if(patch_addr == 0xffff) {
1026 int patch_len = header[patch_ofs++];
1027 for(int i = 0; i < patch_len; i++) {
1028 ram[patch_addr + i] = header[patch_ofs++];
1031 for(int i = 0x40; i < patch_ofs; i++) {
1037 MZT_PUT_SIGNAL(0, sample_rate);
1038 #if defined(_MZ80B) || defined(_MZ2000) || defined(_MZ2200)
1040 MZT_PUT_BIT(0, 22000);
1043 MZT_PUT_BLOCK(header, 128);
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);
1051 MZT_PUT_BLOCK(ram + offs, size);
1054 // format info written in
\8e\8e\8c±
\82É
\8fo
\82éX1
1055 MZT_PUT_BIT(0, 10000);
1059 MZT_PUT_BLOCK(header, 128);
1061 MZT_PUT_BIT(0, 256);
1062 MZT_PUT_BLOCK(header, 128);
1064 MZT_PUT_SIGNAL(0, sample_rate);
1065 MZT_PUT_BIT(0, 10000);
1069 MZT_PUT_BLOCK(ram + offs, size);
1076 // NEC PC-6001/6601 series tape image
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; \
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; \
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; \
1107 int DATAREC::load_p6_image(bool is_p6t)
1109 sample_rate = 48000;
1110 sample_usec = 1000000. / sample_rate;
1112 int ptr = 0, remain = 0x10000, data;
1114 // get info block offset
1115 play_fio->Fseek(-4, FILEIO_SEEK_END);
1116 int length = play_fio->FgetInt32();
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();
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;
1143 remain = min(length, 0x10000);
1146 play_fio->Fseek(0, FILEIO_SEEK_SET);
1148 for(int i = 0; i < 9600; i++) {
1151 for(int i = 0; i < 16; i++) {
1152 data = play_fio->Fgetc();
1154 for(int j = 0; j < 8; j++) {
1155 if(data & (1 << j)) {
1166 // for(int i = 0; i < 1280; i++) {
1167 for(int i = 0; i < 2400; i++) {
1170 while((data = play_fio->Fgetc()) != EOF && remain > 0) {
1172 for(int j = 0; j < 8; j++) {
1173 if(data & (1 << j)) {
1185 for(int i = 0; i < 16; i++) {
1187 for(int j = 0; j < 8; j++) {
1198 // standard cas image for my emulator
1200 static const uint8_t msx_cas_header[8] = {0x1f, 0xa6, 0xde, 0xba, 0xcc, 0x13, 0x7d, 0x74};
1202 int DATAREC::load_cas_image()
1204 sample_rate = 48000;
1205 sample_usec = 1000000. / sample_rate;
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);
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);
1221 // this is the standard cas image for my emulator
1222 play_fio->Fseek(0, FILEIO_SEEK_SET);
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;
1235 // SORD M5 tape image
1237 #define M5_PUT_BIT(val, len) { \
1239 while(remain > 0) { \
1240 if(buffer != NULL) { \
1241 buffer[ptr] = val ? 0 : 0xff; \
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); \
1252 M5_PUT_BIT(0xff, 8); \
1253 M5_PUT_BIT(0x00, 7); \
1255 M5_PUT_BIT(0xff, 16); \
1256 M5_PUT_BIT(0x00, 14); \
1261 int DATAREC::load_m5_cas_image()
1263 play_fio->Fseek(16, FILEIO_SEEK_SET);
1264 int ptr = 0, block_type;
1266 while((block_type = play_fio->Fgetc()) != EOF) {
1267 if(block_type != 'H' && block_type != 'D') {
1270 int block_size = play_fio->Fgetc();
1272 if(block_type == 'H') {
1273 M5_PUT_BIT(0x00, 1);
1275 for(int i = 0; i < (block_type == 'H' ? 945 : 59); i++) {
1276 M5_PUT_BIT(0xff, 8);
1277 M5_PUT_BIT(0x00, 7);
1279 M5_PUT_BYTE(block_type);
1280 M5_PUT_BYTE(block_size);
1282 for(int i = 0; i < ((block_size == 0) ? 0x101 : (block_size + 1)); i++) {
1283 uint8_t data = play_fio->Fgetc();
1286 M5_PUT_BIT(0xff, 8);
1287 M5_PUT_BIT(0x00, 7);
1289 M5_PUT_BIT(0x00, 1);
1293 // ASCII MSX tape image (fMSX)
1294 // MAME/MESS /src/lib/formats/fmsx_cas.c by Mr.Sean Young
1296 #define CAS_PERIOD (16)
1297 #define CAS_HEADER_PERIODS (4000)
1298 #define CAS_EMPTY_PERIODS (1000)
1300 int DATAREC::load_msx_cas_image()
1302 sample_rate = 22050;
1303 sample_usec = 1000000. / sample_rate;
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);
1311 int cas_pos, bit, state = 1, samples_pos, size, n, i, p;
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;
1323 if(buffer != NULL) {
1324 buffer[samples_pos] = 0;
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);
1335 samples_pos += CAS_PERIOD / 4 ;
1342 for(i = 0; i <= 11; i++) {
1346 bit = (bytes[cas_pos] & (1 << (i - 1) ) );
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);
1360 samples_pos += size;
1369 void DATAREC::mix(int32_t* buffer, int cnt)
1371 int32_t* buffer_tmp = buffer;
1373 if(config.tape_sound && pcm_changed && remote && (play || rec) && ff_rew == 0) {
1374 bool signal = ((play && in_signal) || (rec && out_signal));
1376 pcm_positive_clocks += get_passed_clock(pcm_prev_clock);
1378 pcm_negative_clocks += get_passed_clock(pcm_prev_clock);
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;
1383 pcm_last_vol_l = apply_volume(sample, pcm_volume_l);
1384 pcm_last_vol_r = apply_volume(sample, pcm_volume_r);
1386 for(int i = 0; i < cnt; i++) {
1387 *buffer++ += pcm_last_vol_l; // L
1388 *buffer++ += pcm_last_vol_r; // R
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
1396 if(pcm_last_vol_l > 0) {
1398 } else if(pcm_last_vol_l < 0) {
1401 if(pcm_last_vol_r > 0) {
1403 } else if(pcm_last_vol_r < 0) {
1408 pcm_prev_clock = get_current_clock();
1409 pcm_positive_clocks = pcm_negative_clocks = 0;
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
1424 void DATAREC::set_volume(int ch, int decibel_l, int decibel_r)
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);
1437 #define STATE_VERSION 6
1439 void DATAREC::save_state(FILEIO* state_fio)
1441 state_fio->FputUint32(STATE_VERSION);
1442 state_fio->FputInt32(this_device_id);
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;
1461 state_fio->FputInt32(0);
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);
1475 state_fio->FputInt32(buffer_length);
1476 state_fio->Fwrite(buffer, buffer_length, 1);
1478 state_fio->FputInt32(0);
1481 state_fio->FputInt32(buffer_length);
1482 state_fio->Fwrite(buffer_bak, buffer_length, 1);
1484 state_fio->FputInt32(0);
1486 #ifdef DATAREC_SOUND
1488 state_fio->FputInt32(sound_buffer_length);
1489 state_fio->Fwrite(sound_buffer, sound_buffer_length, 1);
1491 state_fio->FputInt32(0);
1493 state_fio->FputInt16(sound_sample);
1495 state_fio->FputBool(is_wav);
1496 state_fio->FputBool(is_tap);
1498 state_fio->FputInt32(apss_buffer_length);
1499 state_fio->Fwrite(apss_buffer, apss_buffer_length, 1);
1501 state_fio->FputInt32(0);
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);
1513 bool DATAREC::load_state(FILEIO* state_fio)
1517 if(state_fio->FgetUint32() != STATE_VERSION) {
1520 if(state_fio->FgetInt32() != this_device_id) {
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();
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);
1538 length_tmp -= length_rw;
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);
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);
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);
1565 sound_sample = state_fio->FgetInt16();
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);
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();
1583 pcm_last_vol_l = pcm_last_vol_r = 0;