OSDN Git Service

7b98ca55356025b437d736e6112e59ab1005c362
[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 bool CMT::process_state(FILEIO* state_fio, bool loading)
186 {
187         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
188                 return false;
189         }
190         if(!state_fio->StateCheckInt32(this_device_id)) {
191                 return false;
192         }
193         state_fio->StateBool(is_wav);
194         state_fio->StateBool(rec);
195         state_fio->StateBool(remote);
196         state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
197         if(loading) {
198                 int length_tmp = state_fio->FgetInt32_LE();
199                 if(rec) {
200                         fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
201                         while(length_tmp != 0) {
202                                 uint8_t buffer_tmp[1024];
203                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
204                                 state_fio->Fread(buffer_tmp, length_rw, 1);
205                                 if(fio->IsOpened()) {
206                                         fio->Fwrite(buffer_tmp, length_rw, 1);
207                                 }
208                                 length_tmp -= length_rw;
209                         }
210                 }
211         } else {
212                 if(rec && fio->IsOpened()) {
213                         int length_tmp = (int)fio->Ftell();
214                         fio->Fseek(0, FILEIO_SEEK_SET);
215                         state_fio->FputInt32_LE(length_tmp);
216                         while(length_tmp != 0) {
217                                 uint8_t buffer_tmp[1024];
218                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
219                                 fio->Fread(buffer_tmp, length_rw, 1);
220                                 state_fio->Fwrite(buffer_tmp, length_rw, 1);
221                                 length_tmp -= length_rw;
222                         }
223                 } else {
224                         state_fio->FputInt32_LE(0);
225                 }
226         }
227         state_fio->StateInt32(bufcnt);
228         state_fio->StateBuffer(buffer, sizeof(buffer), 1);
229         state_fio->StateInt32(prev_signal);
230         state_fio->StateUint32(prev_clock);
231         return true;
232 }