-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathDDSGroup3.h
234 lines (205 loc) · 6.41 KB
/
DDSGroup3.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
//
// Copyright 2018, Jeremy Cooper
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
//
// 1. Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
// COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
// LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#ifndef RDAT_DDS_GROUP_3_H
#define RDAT_DDS_GROUP_3_H
#include <stdint.h>
#include "Track.h"
#include "DATFrame.h"
#include "DDSSubcode.h"
//
// From ECMA DDS specification, section 9.3.3 G3 Sub-Group
//
// A G3 group is one of the 22 pieces that, together, make up a Basic
// Group, which is about 126k of continuous data from the host.
//
class DDSGroup3 {
public:
DDSGroup3();
~DDSGroup3();
//
// 9.4.9.1.1 SW1 Byte
//
// Although it is documented deep within the section of the DDS standard
// that deals with the encoding of raw 35-byte blocks, frames come with an
// area identifier that help mark which region of the tape is being read.
//
// Area identifiers are 3-bit quantities (xxx). They always appear together
// with a single bit "partition" marker (Y) which appears at the
// most-significant nibble of the two combined:
//
// Yxxx
//
typedef enum {
DEVICE_AREA = 0,
REFERENCE_AREA = 1,
SYSTEM_AREA = 2,
DATA_AREA = 4,
EOD_AREA = 5
} AreaID;
//
// A tape can have two partitions.
//
typedef enum {
PARTITION_ONE = 1,
PARTITION_ZERO = 0
} PartitionID;
enum DecodeError {
// Track pair ok. Frame complete.
DECODE_OK,
// A is missing its subcode 3 pack, can't determine frame number
A_MISSING_SUBCODE_3,
// B is missing its subcode 3 pack, can't determine frame number
B_MISSING_SUBCODE_3,
// Neither A nor B had a valid subcode 1 pack
MISSING_SUBCODE_1,
// Neither A nor B had a valid subcode 2 pack
MISSING_SUBCODE_2,
// Neither A nor B had a valid subcode 4 pack
MISSING_SUBCODE_4,
// A and B are not from the same absolute frame.
ABSOLUTE_FRAME_MISMATCH,
// A and B are not from the same logical frame.
LOGICAL_FRAME_MISMATCH,
// Tape area ID is weird.
UNKNOWN_AREA_ID,
// Some of the bytes of the frame are likely corrupted as the
// C2 error correction failed.
C2_ERRORS_PRESENT,
// Frame purports to be ok, but header row doesn't look right.
INVALID_HEADER,
// Fourth checksum mismatch (very hard to explain)
ECC4_ERROR
};
///////////////////////////////////////////////////////////////////////////
// Construction methods.
///////////////////////////////////////////////////////////////////////////
//
// Decode a frame from the given track pair.
//
DecodeError DecodeFrame(const Track& A, const Track& B);
///////////////////////////////////////////////////////////////////////////
// Informational/meta-data methods.
///////////////////////////////////////////////////////////////////////////
//
// Access the underlying DAT frame object.
//
const DATFrame& Frame() const;
//
// The tape area to which this frame purports to belong.
//
AreaID Area() const;
//
// The partition to which this frame purports to belong.
//
PartitionID Partition() const;
//
// Absolute frame number. This frame's id relative to the entire
// tape.
//
uint32_t AbsoluteFrameID() const;
//////////////////////////////////////////////
// Data area frames also support the following
//
//
// The running Basic Group count.
//
uint32_t BasicGroupID() const;
//
// The running Separator 1 count (file count).
//
uint32_t Separator1Count() const;
//
// The running record count.
//
uint32_t RecordCount() const;
//
// The logical frame number. (This G1 group's position within the larger
// Basic Group it is a part of).
//
// I believe this is only valid for frames in the DATA area.
//
uint8_t LogicalFrameID() const;
//
// Whether this is the last frame in the Basic Group.
//
// Again, probably only valid for frames in the DATA area.
//
bool IsLastLogicalFrame() const;
//
// Whether or not this is an ECC3 frame. Generally if this is true
// then IsLastLogicalFrame() should also be true.
//
bool IsECC3Frame() const;
//
// End Data area specific items.
///////////////////////////////////////////////
//
// Give a human-readable description of the given decode error.
//
static const char * ErrorDescription(DecodeError r);
protected:
DecodeError HandleDataAreaFrame(const DDSSubcodePack3& sub3, const Track& A,
const Track& B);
//
// The tape area to which this frame purports to belong.
//
AreaID mAreaID;
//
// Identifiers which are common to all tape areas.
//
PartitionID mPartitionID;
uint32_t mAbsoluteFrameID;
//
// For data areas, the following record the frame's position within
// the data set.
//
// Group.Frame
//
uint32_t mBasicGroupID;
uint8_t mLogicalFrameID;
bool mIsLastLogicalFrame;
bool mIsECC3Frame;
//
// Within a group any number of boundaries can occur:
//
// - A new file (Separator 1)
// - A new set mark (Separator 2)
// - A new record (Record mark)
//
// Each group records the current running tally of each of these marks:
//
uint32_t mSeparator1Count;
uint32_t mSeparator2Count;
uint32_t mRecordCount;
//
// The data in this group.
//
DATFrame mFrame;
};
#endif