OSDN Git Service

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