OSDN Git Service

455c548cbc97d2653a717b3fd2f6232d07ff2a58
[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
12 #define SAMPLE_RATE 48000
13
14 void CMT::initialize()
15 {
16         fio = new FILEIO();
17         rec = remote = false;
18 }
19
20 void CMT::release()
21 {
22         close_tape();
23         delete fio;
24 }
25
26 void CMT::reset()
27 {
28         close_tape();
29         rec = remote = false;
30 }
31
32 void CMT::write_buffer(uint8_t value, int samples)
33 {
34         if(is_wav) {
35                 for(int i = 0; i < samples; i++) {
36                         buffer[bufcnt++] = value;
37                         if(bufcnt == sizeof(buffer)) {
38                                 fio->Fwrite(buffer, sizeof(buffer), 1);
39                                 bufcnt = 0;
40                         }
41                 }
42         } else {
43                 value = (value > 128) ? 0x80 : 0;
44                 while(samples > 0) {
45                         int s = min(samples, 0x7f);
46                         samples -= s;
47                         buffer[bufcnt++] = value | s;
48                         if(bufcnt == sizeof(buffer)) {
49                                 fio->Fwrite(buffer, sizeof(buffer), 1);
50                                 bufcnt = 0;
51                         }
52                 }
53         }
54 }
55
56 void CMT::put_signal()
57 {
58         if(rec && remote) {
59                 uint32_t clock = get_passed_clock(prev_clock);
60                 if(prev_signal == 1) {
61                         // 2400Hz
62                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5) * 2;
63                         for(int i = 0; i < count; i++) {
64                                 write_buffer(0xff, SAMPLE_RATE / 2400 / 2);
65                                 write_buffer(0x00, SAMPLE_RATE / 2400 / 2);
66                         }
67                 } else if(prev_signal == -1) {
68                         // 1200Hz
69                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5);
70                         for(int i = 0; i < count; i++) {
71                                 write_buffer(0xff, SAMPLE_RATE / 1200 / 2);
72                                 write_buffer(0x00, SAMPLE_RATE / 1200 / 2);
73                         }
74                 } else {
75                         write_buffer(0x80, SAMPLE_RATE * clock / CPU_CLOCKS);
76                 }
77         }
78 }
79
80 void CMT::write_signal(int id, uint32_t data, uint32_t mask)
81 {
82         bool next = ((data & mask) != 0);
83         
84         if(id == SIG_CMT_REMOTE) {
85                 if(!remote && next) {
86                         // start
87                         prev_signal = 0;
88                         prev_clock = get_current_clock();
89                 } else if(remote && !next) {
90                         // stop
91                         put_signal();
92                 }
93                 remote = next;
94         } else if(id == SIG_CMT_SOD) {
95                 if(remote) {
96                         request_skip_frames();
97                         put_signal();
98                 }
99                 prev_signal = next ? 1 : -1;
100                 prev_clock = get_current_clock();
101         }
102 }
103
104 void CMT::rec_tape(const _TCHAR* file_path)
105 {
106         close_tape();
107         
108         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
109                 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
110                 if(check_file_extension(file_path, _T(".wav"))) {
111                         write_dummy_wav_header((void *)fio);
112                         is_wav = true;
113                 }
114                 bufcnt = 0;
115                 rec = true;
116         }
117 }
118
119 void CMT::close_tape()
120 {
121         // close file
122         if(rec) {
123                 if(bufcnt) {
124                         fio->Fwrite(buffer, bufcnt, 1);
125                 }
126                 if(is_wav) {
127                         uint32_t length = fio->Ftell();
128                         wav_header_t wav_header;
129                         wav_chunk_t wav_chunk;
130 #if 0                   
131                         
132                         pair_t __riff_chunk_size;
133                         pair_t __fmt_chunk_size;
134                         pair_t __wav_chunk_size;
135                         pair16_t __fmt_id;
136                         pair16_t __channels;
137                         pair_t __sample_rate;
138                         pair16_t __block_size;
139                         pair16_t __sample_bits;
140
141                         __riff_chunk_size.d = length - 8;
142                         __fmt_chunk_size.d = 16;
143                         __fmt_id.w = 1;
144                         __channels.w = 1;
145                         __sample_rate.d = SAMPLE_RATE;
146                         __block_size.w = 1;
147                         __sample_bits.w = 8;
148         
149                         memcpy(wav_header.riff_chunk.id, "RIFF", 4);
150                         wav_header.riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
151         
152                         memcpy(wav_header.wave, "WAVE", 4);
153                         memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
154                         wav_header.fmt_chunk.size = __riff_chunk_size.get_4bytes_le_to();
155                         wav_header.format_id = __fmt_id.get_2bytes_le_to();
156                         wav_header.channels = __channels.get_2byte_le_to();
157                         wav_header.sample_rate = __sample_rate.get_4bytes_le_to();
158                         wav_header.data_speed =  __sample_rate.get_4bytes_le_to();
159                         wav_header.block_size = __block_size.get_2bytes_le_to();
160                         wav_header.sample_bits = __sample_bits_get_2bytes_le_to();
161         
162                         memcpy(wav_chunk.id, "data", 4);
163                         __wav_chunk_size.d = length - sizeof(wav_header) - sizeof(wav_chunk);
164                         wav_chunk.size = __wav_chunk_size.get_4bytes_le_to();
165
166                         
167                         fio->Fseek(0, FILEIO_SEEK_SET);
168                         fio->Fwrite(&wav_header, sizeof(wav_header), 1);
169                         fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
170 #else
171                         if(set_wav_header(&wav_header, &wav_chunk, 1, SAMPLE_RATE, 8, length)) {
172                                 fio->Fseek(0, FILEIO_SEEK_SET);
173                                 fio->Fwrite(&wav_header, sizeof(wav_header), 1);
174                                 fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
175                         }
176 #endif
177                 }
178                 fio->Fclose();
179         }
180         is_wav = rec = false;
181 }
182
183 #define STATE_VERSION   1
184
185 #include "../../statesub.h"
186
187 void CMT::decl_state()
188 {
189         enter_decl_state(STATE_VERSION);
190
191         DECL_STATE_ENTRY_BOOL(is_wav);
192         DECL_STATE_ENTRY_BOOL(rec);
193         DECL_STATE_ENTRY_BOOL(remote);
194         DECL_STATE_ENTRY_STRING(rec_file_path, sizeof(rec_file_path));
195         DECL_STATE_ENTRY_CMT_RECORDING(fio, rec, rec_file_path);
196         
197         DECL_STATE_ENTRY_INT32(bufcnt);
198         DECL_STATE_ENTRY_1D_ARRAY(buffer, sizeof(buffer));
199         DECL_STATE_ENTRY_INT32(prev_signal);
200         DECL_STATE_ENTRY_UINT32(prev_clock);
201
202         leave_decl_state();
203 }
204
205 void CMT::save_state(FILEIO* state_fio)
206 {
207         if(state_entry != NULL) {
208                 state_entry->save_state(state_fio);
209         }
210 //      state_fio->FputUint32(STATE_VERSION);
211 //      state_fio->FputInt32(this_device_id);
212 //      
213 //      state_fio->FputBool(is_wav);
214 //      state_fio->FputBool(rec);
215 //      state_fio->FputBool(remote);
216 //      state_fio->Fwrite(rec_file_path, sizeof(rec_file_path), 1);
217 //      if(rec && fio->IsOpened()) {
218 //              int length_tmp = (int)fio->Ftell();
219 //              fio->Fseek(0, FILEIO_SEEK_SET);
220 //              state_fio->FputInt32(length_tmp);
221 //              while(length_tmp != 0) {
222 //                      uint8_t buffer_tmp[1024];
223 //                      int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
224 //                      fio->Fread(buffer_tmp, length_rw, 1);
225 //                      state_fio->Fwrite(buffer_tmp, length_rw, 1);
226 //                      length_tmp -= length_rw;
227 //              }
228 //      } else {
229 //              state_fio->FputInt32(0);
230 //      }
231 //      state_fio->FputInt32(bufcnt);
232 //      state_fio->Fwrite(buffer, sizeof(buffer), 1);
233 //      state_fio->FputInt32(prev_signal);
234 //      state_fio->FputUint32(prev_clock);
235 }
236
237 bool CMT::load_state(FILEIO* state_fio)
238 {
239         close_tape();
240         
241         bool mb = false;
242         if(state_entry != NULL) {
243                 mb = state_entry->load_state(state_fio);
244         }
245         if(!mb) {
246                 return false;
247         }
248 //      if(state_fio->FgetUint32() != STATE_VERSION) {
249 //              return false;
250 //      }
251 //      if(state_fio->FgetInt32() != this_device_id) {
252 //              return false;
253 //      }
254 //      is_wav = state_fio->FgetBool();
255 //      rec = state_fio->FgetBool();
256 //      remote = state_fio->FgetBool();
257 //      state_fio->Fread(rec_file_path, sizeof(rec_file_path), 1);
258 //      int length_tmp = state_fio->FgetInt32();
259 //      if(rec) {
260 //              fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
261 //              while(length_tmp != 0) {
262 //                      uint8_t buffer_tmp[1024];
263 //                      int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
264 //                      state_fio->Fread(buffer_tmp, length_rw, 1);
265 //                      if(fio->IsOpened()) {
266 //                              fio->Fwrite(buffer_tmp, length_rw, 1);
267 //                      }
268 //                      length_tmp -= length_rw;
269 //              }
270 //      }
271 //      bufcnt = state_fio->FgetInt32();
272 //      state_fio->Fread(buffer, sizeof(buffer), 1);
273 //      prev_signal = state_fio->FgetInt32();
274 //      prev_clock = state_fio->FgetUint32();
275         return true;
276 }
277
278 bool CMT::process_state(FILEIO* state_fio, bool loading)
279 {
280         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
281                 return false;
282         }
283         if(!state_fio->StateCheckInt32(this_device_id)) {
284                 return false;
285         }
286         state_fio->StateBool(is_wav);
287         state_fio->StateBool(rec);
288         state_fio->StateBool(remote);
289         state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
290         if(loading) {
291                 int length_tmp = state_fio->FgetInt32_LE();
292                 if(rec) {
293                         fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
294                         while(length_tmp != 0) {
295                                 uint8_t buffer_tmp[1024];
296                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
297                                 state_fio->Fread(buffer_tmp, length_rw, 1);
298                                 if(fio->IsOpened()) {
299                                         fio->Fwrite(buffer_tmp, length_rw, 1);
300                                 }
301                                 length_tmp -= length_rw;
302                         }
303                 }
304         } else {
305                 if(rec && fio->IsOpened()) {
306                         int length_tmp = (int)fio->Ftell();
307                         fio->Fseek(0, FILEIO_SEEK_SET);
308                         state_fio->FputInt32_LE(length_tmp);
309                         while(length_tmp != 0) {
310                                 uint8_t buffer_tmp[1024];
311                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
312                                 fio->Fread(buffer_tmp, length_rw, 1);
313                                 state_fio->Fwrite(buffer_tmp, length_rw, 1);
314                                 length_tmp -= length_rw;
315                         }
316                 } else {
317                         state_fio->FputInt32_LE(0);
318                 }
319         }
320         state_fio->StateInt32(bufcnt);
321         state_fio->StateBuffer(buffer, sizeof(buffer), 1);
322         state_fio->StateInt32(prev_signal);
323         state_fio->StateUint32(prev_clock);
324         return true;
325 }