OSCR
Open Source Cartridge Reader
Loading...
Searching...
No Matches
CRDB.h
1/********************************************************************
2* Open Source Cartridge Reader *
3********************************************************************/
4#pragma once
5#ifndef CRDB_H_
6# define CRDB_H_
7
8# include "config.h"
9# include "syslibinc.h"
10# include "hardware/outputs/Serial.h"
11# include "ui.h"
12# include "common/specializations.h"
13# include "common/crc32.h"
14
15namespace OSCR
16{
17 namespace CRDB
18 {
19 constexpr uint8_t const kDefaultDatabasePathLength = 32;
20 extern uint32_t const PROGMEM kDatabaseFileHeader;
21 extern uint16_t const PROGMEM kVersion;
22 extern uint32_t const PROGMEM kDatestampMinimum;
23 extern char const PROGMEM PATH_TEMPLATE[];
24 extern char const PROGMEM PATH_TEMPLATE_FS[];
25
26 enum class CRDBType : uint8_t
27 {
28 NamedByCRC32, // Search by CRC32, has Name
29 ByID, // Search by ID (uint16_t), unnamed
30 NamedByID, // Search by ID (uint16_t), has Name
31 };
32
33 using OSCR::Storage::sd;
34 using OSCR::Storage::Shared::sharedFile;
35 using OSCR::Storage::Shared::sharedFileName;
36
37 enum ERRORS: uint8_t
38 {
39 E_NONE = 0,
40 E_REACHED_EOF,
41 E_DATABASE_ERROR,
42 E_DATABASE_NOT_FOUND,
43 E_RECORD_NOT_FOUND,
44 E_READ_ERROR,
45 };
46
47 extern void dbName(char const * databaseName, char databasePath[], uint8_t maxLength = kDefaultDatabasePathLength);
48 extern void dbName_P(__FlashStringHelper const * databaseName, char databasePath[], uint8_t maxLength = kDefaultDatabasePathLength);
49
50 /*C******************************************************************
51 * NAME : GenericCartRecord / GenericRecord
52 *
53 * DESCRIPTION :
54 * Extend this generic CRDB record template to make a
55 * database record class.
56 *
57 * USAGE : ...
58 *
59 * NOTES : ...
60 *C*/
61 template<typename RecordType>
63 {
64 public:
65 uint32_t getCRC32() const
66 {
67 return _data.crc32;
68 }
69
70 RecordType * data()
71 {
72 return &_data;
73 }
74
75 protected:
76 RecordType _data = RecordType();
77 };
78
79 template<typename RecordType>
81 {
82 public:
83 RecordType * data()
84 {
85 return &_data;
86 }
87
88 protected:
89 RecordType _data = RecordType();
90 };
91
92 class CRDBBase
93 {
94 public:
95 CRDBBase(char const * crdb_filename, uint_fast32_t crdb_recordsize);
96 CRDBBase(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize);
97
98 virtual ~CRDBBase();
99 virtual void nextRecord() = 0;
100
101 void error(ERRORS code);
102 ERRORS getError() const;
103 bool hasError() const;
104 void clearError();
105
106 void databaseError();
107
108 int16_t readBytes(void * dest, uint8_t bytes);
109 uint8_t readNum8(uint8_t * dest);
110 uint8_t readNum16(uint16_t * dest);
111 uint8_t readNum32(uint32_t * dest);
112 uint8_t readNum32(crc32_t & dest);
113
114 uint32_t numRecords() const;
115
116 bool loadRecordIndex(uint16_t index);
117 bool gotoRecordIndex(uint16_t index);
118
119#if defined(NEEDS_CRDB_ISQUIET)
120 bool isQuiet();
121 void quiet(bool shouldBeQuiet = true);
122#endif
123
124 protected:
125 FsFile file;
126 uint_fast16_t const recordSize;
127 uint_fast16_t recordCount;
128 uint_fast16_t recordNum = 0;
129#if defined(NEEDS_CRDB_ISQUIET)
130 bool beQuiet = false;
131#endif
132 ERRORS errorCode = E_NONE;
133
134 void openDatabase(char const * crdb_filename);
135 };
136
137 class CRDBByIDBase : public CRDBBase
138 {
139 public:
140 CRDBByIDBase(char const * crdb_filename, uint_fast32_t crdb_recordsize)
141 : CRDBBase(crdb_filename, crdb_recordsize)
142 {
143 // ...
144 }
145
146 CRDBByIDBase(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize)
147 : CRDBBase(crdb_filename, crdb_recordsize)
148 {
149 // ...
150 }
151
152 bool findRecord(uint16_t const idSearch, uint16_t const offset = 0);
153 };
154
155 template <typename RecordType>
156 class CRDBByID : public CRDBByIDBase
157 {
158 public:
159 CRDBByID(char const * crdb_filename, uint_fast32_t crdb_recordsize)
160 : CRDBByIDBase(crdb_filename, crdb_recordsize)
161 {
162 // ...
163 }
164
165 CRDBByID(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize)
166 : CRDBByIDBase(crdb_filename, crdb_recordsize)
167 {
168 // ...
169 }
170
171 inline
172 RecordType * record()
173 {
174 return currentRecord;
175 }
176
177 protected:
178 RecordType * currentRecord = new RecordType();
179 };
180
181 template <typename RecordType>
182 class CRDBNamedByID : public CRDBByIDBase
183 {
184 public:
185 CRDBNamedByID(char const * crdb_filename, uint_fast32_t crdb_recordsize)
186 : CRDBByIDBase(crdb_filename, crdb_recordsize)
187 {
188 // ...
189 }
190
191 CRDBNamedByID(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize)
192 : CRDBByIDBase(crdb_filename, crdb_recordsize)
193 {
194 // ...
195 }
196
197 inline
198 RecordType * record()
199 {
200 return currentRecord;
201 }
202
203 inline
204 char * getRecordName() const
205 {
206 return currentRecord->data()->name;
207 }
208
209 protected:
210 RecordType * currentRecord = new RecordType();
211 };
212
213 class CRDBNamedByCRC32Base : public CRDBBase
214 {
215 public:
216 CRDBNamedByCRC32Base(char const * crdb_filename, uint_fast32_t crdb_recordsize)
217 : CRDBBase(crdb_filename, crdb_recordsize)
218 {
219 // ...
220 }
221
222 CRDBNamedByCRC32Base(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize)
223 : CRDBBase(crdb_filename, crdb_recordsize)
224 {
225 // ...
226 }
227
228 bool findRecord(uint32_t const crc32, uint16_t const offset = 0);
229 bool findRecord(crc32_t const & crc32search, uint16_t const offset = 0);
230 bool findEitherRecord(crc32_t crc32search1, crc32_t crc32search2, uint16_t offset = 0);
231
232 bool matchCRC(uint32_t crc32, int dbOffset = 0);
233 bool matchCRC(crc32_t & crc32, int dbOffset = 0);
234 bool matchCRC(crc32_t * crc32ptr = nullptr, int dbOffset = 0);
235
236 // CRC match events
237#if defined(NEEDS_CRDB_EVENTS) || defined(NEEDS_CRDB_EVENT_POSTMATCHCRC)
238 virtual bool postMatchCRC() = 0;
239#endif
240#if defined(NEEDS_CRDB_EVENTS) || defined(NEEDS_CRDB_EVENT_CRCMATCHFAIL)
241 virtual bool crcMatchFail() = 0;
242#endif
243#if defined(NEEDS_CRDB_EVENTS) || defined(NEEDS_CRDB_EVENT_CRCMATCHSUCCESS)
244 virtual bool crcMatchSuccess() = 0;
245#endif
246
247 virtual char * getRecordName() const = 0;
248
249 protected:
250 virtual bool cmprCRC32(crc32_t * crc32ptr = nullptr) const = 0;
251 // ...
252 };
253
254 template <typename RecordType>
255 class CRDBNamedByCRC32 : public CRDBNamedByCRC32Base
256 {
257 public:
258 CRDBNamedByCRC32(char const * crdb_filename, uint_fast32_t crdb_recordsize)
259 : CRDBNamedByCRC32Base(crdb_filename, crdb_recordsize)
260 {
261 // ...
262 }
263
264 CRDBNamedByCRC32(__FlashStringHelper const * crdb_filename, uint_fast32_t crdb_recordsize)
265 : CRDBNamedByCRC32Base(crdb_filename, crdb_recordsize)
266 {
267 // ...
268 }
269
270 inline
271 RecordType * record()
272 {
273 return currentRecord;
274 }
275
276 inline
277 char * getRecordName() const override
278 {
279 return currentRecord->data()->name;
280 }
281
282 protected:
283 RecordType * currentRecord = new RecordType();
284
285 inline
286 bool cmprCRC32(crc32_t * crc32ptr = nullptr) const override
287 {
288 return (*crc32ptr == currentRecord->getCRC32());
289 }
290 };
291
292 template <typename RecordType, CRDBType crdbType> struct get_crdb_class { typedef void type; };
293 template <typename RecordType> struct get_crdb_class <RecordType, CRDBType::NamedByCRC32> { typedef CRDBNamedByCRC32<RecordType> type; };
294 template <typename RecordType> struct get_crdb_class <RecordType, CRDBType::NamedByID> { typedef CRDBNamedByID<RecordType> type; };
295 template <typename RecordType> struct get_crdb_class <RecordType, CRDBType::ByID> { typedef CRDBByID<RecordType> type; };
296
297 /*C******************************************************************
298 * NAME : CRDB
299 *
300 * DESCRIPTION :
301 * Extend this generic CRDB template with the record class
302 * as the type parameter to create a new DB type.
303 *
304 * USAGE : ...
305 *
306 * NOTES : ...
307 *C*/
308 template <typename RecordType,
309 uint_fast32_t dbRecordSize,
310 CRDBType crdbType = CRDBType::NamedByCRC32,
311 typename CRDBParent = typename get_crdb_class<RecordType, crdbType>::type>
312 class CRDB : public CRDBParent
313 {
314 public:
315 CRDB(char const * crdb_filename)
316 : CRDBParent(crdb_filename, dbRecordSize)
317 {
318 // ...
319 }
320
321 CRDB(__FlashStringHelper const * crdb_filename)
322 : CRDBParent(crdb_filename, dbRecordSize)
323 {
324 // ...
325 }
326
327 protected:
328 // ...
329 };
330 }
331}
332
333#endif /* CRDB_H_ */
Definition CRDB.h:157
Definition CRDB.h:256
Definition CRDB.h:183
Definition CRDB.h:63
Definition CRDB.h:81
Main program.
Definition Storage.h:13
Definition CRDB.h:292
Interface for handling CRC32 values.
Definition crc32_t.h:14