OSDN Git Service

[General] Convert sourcecode's CRLF format: DOS(WINDOWS) to Unix, to apply patches...
[csp-qt/common_source_project-fm7.git] / source / src / vm / pc8201 / cmt.cpp
1 /*
2         NEC PC-8201 Emulator 'ePC-8201'
3
4         Author : Takeda.Toshiya
5         Date   : 2013.04.22-
6
7         [ cmt (record only) ]
8 */
9
10 #include "cmt.h"
11 #include "../../fileio.h"
12
13 #pragma pack(1)
14 typedef struct {
15         char id[4];
16         uint32 size;
17 } wav_chunk_t;
18 #pragma pack()
19
20 #pragma pack(1)
21 typedef struct {
22         wav_chunk_t riff_chunk;
23         char wave[4];
24         wav_chunk_t fmt_chunk;
25         uint16 format_id;
26         uint16 channels;
27         uint32 sample_rate;
28         uint32 data_speed;
29         uint16 block_size;
30         uint16 sample_bits;
31 } wav_header_t;
32 #pragma pack()
33
34 #define SAMPLE_RATE 48000
35
36 void CMT::initialize()
37 {
38         fio = new FILEIO();
39         rec = remote = false;
40 }
41
42 void CMT::release()
43 {
44         close_tape();
45         delete fio;
46 }
47
48 void CMT::reset()
49 {
50         close_tape();
51         rec = remote = false;
52 }
53
54 void CMT::write_buffer(uint8 value, int samples)
55 {
56         if(is_wav) {
57                 for(int i = 0; i < samples; i++) {
58                         buffer[bufcnt++] = value;
59                         if(bufcnt == sizeof(buffer)) {
60                                 fio->Fwrite(buffer, sizeof(buffer), 1);
61                                 bufcnt = 0;
62                         }
63                 }
64         } else {
65                 value = (value > 128) ? 0x80 : 0;
66                 while(samples > 0) {
67                         int s = min(samples, 0x7f);
68                         samples -= s;
69                         buffer[bufcnt++] = value | s;
70                         if(bufcnt == sizeof(buffer)) {
71                                 fio->Fwrite(buffer, sizeof(buffer), 1);
72                                 bufcnt = 0;
73                         }
74                 }
75         }
76 }
77
78 void CMT::put_signal()
79 {
80         if(rec && remote) {
81                 uint32 clock = passed_clock(prev_clock);
82                 if(prev_signal == 1) {
83                         // 2400Hz
84                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5) * 2;
85                         for(int i = 0; i < count; i++) {
86                                 write_buffer(0xff, SAMPLE_RATE / 2400 / 2);
87                                 write_buffer(0x00, SAMPLE_RATE / 2400 / 2);
88                         }
89                 } else if(prev_signal == -1) {
90                         // 1200Hz
91                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5);
92                         for(int i = 0; i < count; i++) {
93                                 write_buffer(0xff, SAMPLE_RATE / 1200 / 2);
94                                 write_buffer(0x00, SAMPLE_RATE / 1200 / 2);
95                         }
96                 } else {
97                         write_buffer(0x80, SAMPLE_RATE * clock / CPU_CLOCKS);
98                 }
99         }
100 }
101
102 void CMT::write_signal(int id, uint32 data, uint32 mask)
103 {
104         bool next = ((data & mask) != 0);
105         
106         if(id == SIG_CMT_REMOTE) {
107                 if(!remote && next) {
108                         // start
109                         prev_signal = 0;
110                         prev_clock = current_clock();
111                 } else if(remote && !next) {
112                         // stop
113                         put_signal();
114                 }
115                 remote = next;
116         } else if(id == SIG_CMT_SOD) {
117                 if(remote) {
118                         request_skip_frames();
119                         put_signal();
120                 }
121                 prev_signal = next ? 1 : -1;
122                 prev_clock = current_clock();
123         }
124 }
125
126 void CMT::rec_tape(_TCHAR* file_path)
127 {
128         close_tape();
129         
130         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
131                 if(check_file_extension(file_path, _T(".wav"))) {
132                         uint8 dummy[sizeof(wav_header_t) + sizeof(wav_chunk_t)];
133                         memset(dummy, 0, sizeof(dummy));
134                         fio->Fwrite(dummy, sizeof(dummy), 1);
135                         is_wav = true;
136                 }
137                 bufcnt = 0;
138                 rec = true;
139         }
140 }
141
142 void CMT::close_tape()
143 {
144         // close file
145         if(rec) {
146                 if(bufcnt) {
147                         fio->Fwrite(buffer, bufcnt, 1);
148                 }
149                 if(is_wav) {
150                         uint32 length = fio->Ftell();
151                         
152                         wav_header_t wav_header;
153                         wav_chunk_t wav_chunk;
154                         
155                         memcpy(wav_header.riff_chunk.id, "RIFF", 4);
156                         wav_header.riff_chunk.size = length - 8;
157                         memcpy(wav_header.wave, "WAVE", 4);
158                         memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
159                         wav_header.fmt_chunk.size = 16;
160                         wav_header.format_id = 1;
161                         wav_header.channels = 1;
162                         wav_header.sample_rate = SAMPLE_RATE;
163                         wav_header.data_speed = SAMPLE_RATE;
164                         wav_header.block_size = 1;
165                         wav_header.sample_bits = 8;
166                         
167                         memcpy(wav_chunk.id, "data", 4);
168                         wav_chunk.size = length - sizeof(wav_header) - sizeof(wav_chunk);
169                         
170                         fio->Fseek(0, FILEIO_SEEK_SET);
171                         fio->Fwrite(&wav_header, sizeof(wav_header), 1);
172                         fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
173                 }
174                 fio->Fclose();
175         }
176         is_wav = rec = false;
177 }
178