OSDN Git Service

[VM][STATE] Use namespace {VMNAME} to separate per VMs.
[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 namespace PC8201 {
15
16 void CMT::initialize()
17 {
18         fio = new FILEIO();
19         rec = remote = false;
20 }
21
22 void CMT::release()
23 {
24         close_tape();
25         delete fio;
26 }
27
28 void CMT::reset()
29 {
30         close_tape();
31         rec = remote = false;
32 }
33
34 void CMT::write_buffer(uint8_t value, int samples)
35 {
36         if(is_wav) {
37                 for(int i = 0; i < samples; i++) {
38                         buffer[bufcnt++] = value;
39                         if(bufcnt == sizeof(buffer)) {
40                                 fio->Fwrite(buffer, sizeof(buffer), 1);
41                                 bufcnt = 0;
42                         }
43                 }
44         } else {
45                 value = (value > 128) ? 0x80 : 0;
46                 while(samples > 0) {
47                         int s = min(samples, 0x7f);
48                         samples -= s;
49                         buffer[bufcnt++] = value | s;
50                         if(bufcnt == sizeof(buffer)) {
51                                 fio->Fwrite(buffer, sizeof(buffer), 1);
52                                 bufcnt = 0;
53                         }
54                 }
55         }
56 }
57
58 void CMT::put_signal()
59 {
60         if(rec && remote) {
61                 uint32_t clock = get_passed_clock(prev_clock);
62                 if(prev_signal == 1) {
63                         // 2400Hz
64                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5) * 2;
65                         for(int i = 0; i < count; i++) {
66                                 write_buffer(0xff, SAMPLE_RATE / 2400 / 2);
67                                 write_buffer(0x00, SAMPLE_RATE / 2400 / 2);
68                         }
69                 } else if(prev_signal == -1) {
70                         // 1200Hz
71                         int count = (int)(1200.0 * (double)clock / (double)CPU_CLOCKS + 0.5);
72                         for(int i = 0; i < count; i++) {
73                                 write_buffer(0xff, SAMPLE_RATE / 1200 / 2);
74                                 write_buffer(0x00, SAMPLE_RATE / 1200 / 2);
75                         }
76                 } else {
77                         write_buffer(0x80, SAMPLE_RATE * clock / CPU_CLOCKS);
78                 }
79         }
80 }
81
82 void CMT::write_signal(int id, uint32_t data, uint32_t mask)
83 {
84         bool next = ((data & mask) != 0);
85         
86         if(id == SIG_CMT_REMOTE) {
87                 if(!remote && next) {
88                         // start
89                         prev_signal = 0;
90                         prev_clock = get_current_clock();
91                 } else if(remote && !next) {
92                         // stop
93                         put_signal();
94                 }
95                 remote = next;
96         } else if(id == SIG_CMT_SOD) {
97                 if(remote) {
98                         request_skip_frames();
99                         put_signal();
100                 }
101                 prev_signal = next ? 1 : -1;
102                 prev_clock = get_current_clock();
103         }
104 }
105
106 void CMT::rec_tape(const _TCHAR* file_path)
107 {
108         close_tape();
109         
110         if(fio->Fopen(file_path, FILEIO_WRITE_BINARY)) {
111                 my_tcscpy_s(rec_file_path, _MAX_PATH, file_path);
112                 if(check_file_extension(file_path, _T(".wav"))) {
113                         write_dummy_wav_header((void *)fio);
114                         is_wav = true;
115                 }
116                 bufcnt = 0;
117                 rec = true;
118         }
119 }
120
121 void CMT::close_tape()
122 {
123         // close file
124         if(rec) {
125                 if(bufcnt) {
126                         fio->Fwrite(buffer, bufcnt, 1);
127                 }
128                 if(is_wav) {
129                         uint32_t length = fio->Ftell();
130                         wav_header_t wav_header;
131                         wav_chunk_t wav_chunk;
132 #if 0                   
133                         
134                         pair_t __riff_chunk_size;
135                         pair_t __fmt_chunk_size;
136                         pair_t __wav_chunk_size;
137                         pair16_t __fmt_id;
138                         pair16_t __channels;
139                         pair_t __sample_rate;
140                         pair16_t __block_size;
141                         pair16_t __sample_bits;
142
143                         __riff_chunk_size.d = length - 8;
144                         __fmt_chunk_size.d = 16;
145                         __fmt_id.w = 1;
146                         __channels.w = 1;
147                         __sample_rate.d = SAMPLE_RATE;
148                         __block_size.w = 1;
149                         __sample_bits.w = 8;
150         
151                         memcpy(wav_header.riff_chunk.id, "RIFF", 4);
152                         wav_header.riff_chunk.size = __riff_chunk_size.get_4bytes_le_to();
153         
154                         memcpy(wav_header.wave, "WAVE", 4);
155                         memcpy(wav_header.fmt_chunk.id, "fmt ", 4);
156                         wav_header.fmt_chunk.size = __riff_chunk_size.get_4bytes_le_to();
157                         wav_header.format_id = __fmt_id.get_2bytes_le_to();
158                         wav_header.channels = __channels.get_2byte_le_to();
159                         wav_header.sample_rate = __sample_rate.get_4bytes_le_to();
160                         wav_header.data_speed =  __sample_rate.get_4bytes_le_to();
161                         wav_header.block_size = __block_size.get_2bytes_le_to();
162                         wav_header.sample_bits = __sample_bits_get_2bytes_le_to();
163         
164                         memcpy(wav_chunk.id, "data", 4);
165                         __wav_chunk_size.d = length - sizeof(wav_header) - sizeof(wav_chunk);
166                         wav_chunk.size = __wav_chunk_size.get_4bytes_le_to();
167
168                         
169                         fio->Fseek(0, FILEIO_SEEK_SET);
170                         fio->Fwrite(&wav_header, sizeof(wav_header), 1);
171                         fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
172 #else
173                         if(set_wav_header(&wav_header, &wav_chunk, 1, SAMPLE_RATE, 8, length)) {
174                                 fio->Fseek(0, FILEIO_SEEK_SET);
175                                 fio->Fwrite(&wav_header, sizeof(wav_header), 1);
176                                 fio->Fwrite(&wav_chunk, sizeof(wav_chunk), 1);
177                         }
178 #endif
179                 }
180                 fio->Fclose();
181         }
182         is_wav = rec = false;
183 }
184
185 #define STATE_VERSION   1
186
187 bool CMT::process_state(FILEIO* state_fio, bool loading)
188 {
189         if(!state_fio->StateCheckUint32(STATE_VERSION)) {
190                 return false;
191         }
192         if(!state_fio->StateCheckInt32(this_device_id)) {
193                 return false;
194         }
195         state_fio->StateBool(is_wav);
196         state_fio->StateBool(rec);
197         state_fio->StateBool(remote);
198         state_fio->StateBuffer(rec_file_path, sizeof(rec_file_path), 1);
199         if(loading) {
200                 int length_tmp = state_fio->FgetInt32_LE();
201                 if(rec) {
202                         fio->Fopen(rec_file_path, FILEIO_READ_WRITE_NEW_BINARY);
203                         while(length_tmp != 0) {
204                                 uint8_t buffer_tmp[1024];
205                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
206                                 state_fio->Fread(buffer_tmp, length_rw, 1);
207                                 if(fio->IsOpened()) {
208                                         fio->Fwrite(buffer_tmp, length_rw, 1);
209                                 }
210                                 length_tmp -= length_rw;
211                         }
212                 }
213         } else {
214                 if(rec && fio->IsOpened()) {
215                         int length_tmp = (int)fio->Ftell();
216                         fio->Fseek(0, FILEIO_SEEK_SET);
217                         state_fio->FputInt32_LE(length_tmp);
218                         while(length_tmp != 0) {
219                                 uint8_t buffer_tmp[1024];
220                                 int length_rw = min(length_tmp, (int)sizeof(buffer_tmp));
221                                 fio->Fread(buffer_tmp, length_rw, 1);
222                                 state_fio->Fwrite(buffer_tmp, length_rw, 1);
223                                 length_tmp -= length_rw;
224                         }
225                 } else {
226                         state_fio->FputInt32_LE(0);
227                 }
228         }
229         state_fio->StateInt32(bufcnt);
230         state_fio->StateBuffer(buffer, sizeof(buffer), 1);
231         state_fio->StateInt32(prev_signal);
232         state_fio->StateUint32(prev_clock);
233         return true;
234 }
235
236 }