17static constexpr std::array<uint8_t, 10> ASCII_HEADER = { 0xEA,0xEA,0xEA,0xEA,0xEA,0xEA,0xEA,0xEA,0xEA,0xEA };
18static constexpr std::array<uint8_t, 10> BINARY_HEADER = { 0xD0,0xD0,0xD0,0xD0,0xD0,0xD0,0xD0,0xD0,0xD0,0xD0 };
19static constexpr std::array<uint8_t, 10> BASIC_HEADER = { 0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3,0xD3 };
62static constexpr unsigned BAUDRATE = 3744;
63static constexpr unsigned OUTPUT_FREQUENCY = 4 * BAUDRATE;
66static constexpr unsigned SHORT_SILENCE = OUTPUT_FREQUENCY * 1;
67static constexpr unsigned LONG_SILENCE = OUTPUT_FREQUENCY * 2;
70static constexpr unsigned LONG_HEADER = 16000 / 2;
71static constexpr unsigned SHORT_HEADER = 4000 / 2;
74static constexpr std::array<uint8_t, 8> CAS_HEADER = { 0x1F,0xA6,0xDE,0xBA,0xCC,0x13,0x7D,0x74 };
76static void write0(std::vector<int8_t>& wave)
78 static constexpr std::array<int8_t, 4> chunk{127, 127, -127, -127};
79 ::append(wave, chunk);
81static void write1(std::vector<int8_t>& wave)
83 static constexpr std::array<int8_t, 4> chunk{127, -127, 127, -127};
84 ::append(wave, chunk);
87static void writeHeader(std::vector<int8_t>& wave,
unsigned s)
89 repeat(s, [&] { write1(wave); });
92static void writeByte(std::vector<int8_t>& wave, uint8_t b)
110static bool writeData(std::vector<int8_t>& wave, std::span<const uint8_t> cas,
size_t& pos)
113 while ((pos + CAS_HEADER.size()) <= cas.size()) {
114 if (compare(&cas[pos], CAS_HEADER)) {
117 writeByte(wave, cas[pos]);
118 if (cas[pos] == 0x1A) {
123 while (pos < cas.size()) {
124 writeByte(wave, cas[pos++]);
129static CasImage::Data convert(std::span<const uint8_t> cas,
const std::string& filename,
CliComm& cliComm,
134 auto& wave = data.
wave;
137 bool issueWarning =
false;
138 bool headerFound =
false;
139 bool firstFile =
true;
141 while ((pos + CAS_HEADER.size()) <= cas.size()) {
142 if (compare(&cas[pos], CAS_HEADER)) {
147 pos += CAS_HEADER.size();
148 writeSilence(wave, LONG_SILENCE);
149 writeHeader(wave, LONG_HEADER);
150 if ((pos + ASCII_HEADER.size()) <= cas.size()) {
153 if (compare(&cas[pos], ASCII_HEADER)) {
155 }
else if (compare(&cas[pos], BINARY_HEADER)) {
157 }
else if (compare(&cas[pos], BASIC_HEADER)) {
163 if (firstFile) firstFileType = type;
166 writeData(wave, cas, pos);
168 pos += CAS_HEADER.size();
169 writeSilence(wave, SHORT_SILENCE);
170 writeHeader(wave, SHORT_HEADER);
171 bool eof = writeData(wave, cas, pos);
173 }
while ((pos + CAS_HEADER.size()) <= cas.size());
177 writeData(wave, cas, pos);
178 writeSilence(wave, SHORT_SILENCE);
179 writeHeader(wave, SHORT_HEADER);
180 pos += CAS_HEADER.size();
181 writeData(wave, cas, pos);
185 writeData(wave, cas, pos);
190 writeData(wave, cas, pos);
200 throw MSXException(filename,
": not a valid CAS image");
203 cliComm.
printWarning(
"Skipped unhandled data in ", filename);
213static constexpr std::array<uint8_t, 17> header = {
214 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
215 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
219static void writeBit(std::vector<int8_t>& wave,
bool bit)
221 size_t count = bit ? 1 : 2;
222 append(wave, count, 127);
223 append(wave, count, -127);
226static void writeByte(std::vector<int8_t>& wave, uint8_t
byte)
228 for (
int i = 7; i >= 0; --i) {
229 writeBit(wave, (
byte >> i) & 1);
233static void processBlock(std::span<const uint8_t> subBuf, std::vector<int8_t>& wave)
235 writeSilence(wave, 1200);
236 writeBit(wave,
true);
237 repeat(199, [&] { writeByte(wave, 0x55); });
238 writeByte(wave, 0x7f);
239 for (uint8_t val : subBuf) {
240 writeBit(wave,
false);
241 writeByte(wave, val);
250 if (cas.size() >= (header.size() + ASCII_HEADER.size())) {
251 if (compare(&cas[header.size()], ASCII_HEADER)) {
253 }
else if (compare(&cas[header.size()], BINARY_HEADER)) {
255 }
else if (compare(&cas[header.size()], BASIC_HEADER)) {
260 auto prevHeader = cas.begin() + header.size();
262 auto nextHeader = std::search(prevHeader, cas.end(),
263 header.begin(), header.end());
264 processBlock(std::span(prevHeader, nextHeader), data.
wave);
265 if (nextHeader == cas.end())
break;
266 prevHeader = nextHeader + header.size();