openMSX
TsxParser.hh
Go to the documentation of this file.
1// Based on code written by:
2// (2017) NataliaPC aka @ishwin74
3// Under GPL License
4
5#ifndef TSXPARSER_HH
6#define TSXPARSER_HH
7
8#include "endian.hh"
9
10#include <array>
11#include <cstdint>
12#include <optional>
13#include <span>
14#include <string>
15#include <vector>
16
17class TsxParser {
18public:
19 // output settings
20 static constexpr unsigned TZX_Z80_FREQ = 3500000; // 3.5MHz (according to TZX spec: not 3.579545MHz)
21 static constexpr unsigned OUTPUT_FREQUENCY = 58900; // ~ = Z80_FREQ * 4 / T_STATES_MSX_PULSE
22 static constexpr float T_STATES_MSX_PULSE = 238.f;
23
24 enum class FileType {
26 };
27
28public:
29 explicit TsxParser(std::span<const uint8_t> file);
30
31 [[nodiscard]] std::vector<int8_t>&& stealOutput() { return std::move(output); }
32 [[nodiscard]] std::optional<FileType> getFirstFileType() const { return firstFileType; }
33 [[nodiscard]] const std::vector<std::string>& getMessages() const { return messages; }
34
35private:
36 struct Block10 {
37 Endian::UA_L16 pauseMs; // Pause after this block in milliseconds
38 Endian::UA_L16 len; // Length of data that follow
39 //uint8_t data[]; // Data as in .TAP files
40 };
41 struct Block11 {
42 Endian::UA_L16 pilot; // Length of PILOT pulse {2168}
43 Endian::UA_L16 sync1; // Length of SYNC first pulse {667}
44 Endian::UA_L16 sync2; // Length of SYNC second pulse {735}
45 Endian::UA_L16 zero; // Length of ZERO bit pulse {855}
46 Endian::UA_L16 one; // Length of ONE bit pulse {1710}
47 Endian::UA_L16 pilotLen; // Length of PILOT tone (number of pulses) {8063 header (flag<128), 3223 data (flag>=128)}
48 uint8_t lastBits; // Used bits in the last byte (other bits should be 0) {8}
49 Endian::UA_L16 pauseMs; // Pause after this block (ms.) {1000}
50 Endian::UA_L24 len; // Length of data that follow
51 //uint8_t data[]; // Data as in .TAP files
52 };
53 struct Block12 {
54 Endian::UA_L16 len; // Length of one pulse in T-states
55 Endian::UA_L16 pulses; // Number of pulses
56 };
57 struct Block13 {
58 uint8_t num; // Number of pulses
59 //Endian::UA_L16 pulses[]; // [Array] Pulses' lengths
60 };
61 struct Block15 {
62 Endian::UA_L16 bitTstates; // Number of T-states per sample (bit of data)
63 Endian::UA_L16 pauseMs; // Pause after this block (ms.) {1000}
64 uint8_t lastBits; // Used bits (samples) in last byte of data (1-8)
65 Endian::UA_L24 len; // Length of samples data
66 //uint8_t samples[]; // [Array] Samples data. Each bit represents a state on the EAR port (i.e. one sample). MSb is played first.
67 };
68 struct Block20 {
69 Endian::UA_L16 pauseMs; // Silence pause in milliseconds
70 };
71 struct Block21 {
72 uint8_t len; // Length of the group name string
73 //char name[]; // The group name (ASCII)
74 };
75 struct Block30 {
76 uint8_t len; // Length of the text description
77 //char text[]; // [Array] Text description in ASCII format
78 };
79 struct Block32 {
80 Endian::UA_L16 blockLen; // Length of the whole block (without these two bytes)
81 uint8_t num; // Number of text strings
82 //uint8_t list[]; // [Array] List of text strings
83 };
84 struct Block35 {
85 std::array<char, 0x10> label;// Identification string (in ASCII)
86 Endian::UA_L32 len; // Length of the custom info
87 //uint8_t data[]; // [Array] Custom info
88 };
89 struct Block4B {
90 Endian::UA_L32 blockLen; // Block length without these four bytes
91 Endian::UA_L16 pauseMs; // Pause after this block in milliseconds
92 Endian::UA_L16 pilot; // Duration of a PILOT pulse in T-states {same as ONE pulse}
93 Endian::UA_L16 pulses; // Number of pulses in the PILOT tone
94 Endian::UA_L16 bit0len; // Duration of a ZERO pulse in T-states {=2*pilot}
95 Endian::UA_L16 bit1len; // Duration of a ONE pulse in T-states {=pilot}
96 uint8_t bitCfg;
97 uint8_t byteCfg;
98 //uint8_t data[]; // [Array]
99 };
100
101 void processBlock10(const Block10& b);
102 void processBlock11(const Block11& b);
103 void processBlock12(const Block12& b);
104 void processBlock13(const Block13& b);
105 void processBlock15(const Block15& b);
106 void processBlock20(const Block20& b);
107 void processBlock21(const Block21& b);
108 void processBlock30(const Block30& b);
109 void processBlock32(const Block32& b);
110 void processBlock35(const Block35& b);
111 void processBlock4B(const Block4B& b);
112
113 void writeSample(uint32_t tStates, int8_t value);
114 void writePulse(uint32_t tStates);
115 void writePulses(uint32_t count, uint32_t tStates);
116 void writeSilence(int s);
117
118 template<typename T> std::span<const T> get(size_t count);
119 template<typename T> const T& get();
120
121 [[noreturn]] void error(std::string msg) const;
122
123private:
124 // The parsed result is stored here
125 std::vector<int8_t> output;
126 std::vector<std::string> messages;
127 std::optional<FileType> firstFileType;
128
129 // The (remaining) part of the input file
130 std::span<const uint8_t> buf;
131
132 // Intermediate state while writing the waveform
133 float accumBytes = 0.f;
134 int8_t currentValue = 127;
135};
136
137#endif
const std::vector< std::string > & getMessages() const
Definition TsxParser.hh:33
static constexpr unsigned TZX_Z80_FREQ
Definition TsxParser.hh:20
static constexpr float T_STATES_MSX_PULSE
Definition TsxParser.hh:22
std::optional< FileType > getFirstFileType() const
Definition TsxParser.hh:32
std::vector< int8_t > && stealOutput()
Definition TsxParser.hh:31
static constexpr unsigned OUTPUT_FREQUENCY
Definition TsxParser.hh:21